deps: upgrade to V8 5.0.71.47
Pick up the latest set of patch level updates from the V8 5.0 branch. https://github.com/v8/v8/compare/5.0.71.35...5.0.71.47 PR-URL: https://github.com/nodejs/node/pull/6572 Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: JungMinu - Minwoo Jung <jmwsoft@gmail.com>
This commit is contained in:
parent
fe4837afcc
commit
e16e611089
2
deps/v8/include/v8-version.h
vendored
2
deps/v8/include/v8-version.h
vendored
@ -11,7 +11,7 @@
|
|||||||
#define V8_MAJOR_VERSION 5
|
#define V8_MAJOR_VERSION 5
|
||||||
#define V8_MINOR_VERSION 0
|
#define V8_MINOR_VERSION 0
|
||||||
#define V8_BUILD_NUMBER 71
|
#define V8_BUILD_NUMBER 71
|
||||||
#define V8_PATCH_LEVEL 35
|
#define V8_PATCH_LEVEL 47
|
||||||
|
|
||||||
// Use 1 for candidates and 0 otherwise.
|
// Use 1 for candidates and 0 otherwise.
|
||||||
// (Boolean macro values are not supported by all preprocessors.)
|
// (Boolean macro values are not supported by all preprocessors.)
|
||||||
|
81
deps/v8/src/arm/code-stubs-arm.cc
vendored
81
deps/v8/src/arm/code-stubs-arm.cc
vendored
@ -671,11 +671,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
|
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
|
|
||||||
__ Push(lhs, rhs);
|
|
||||||
// Figure out which native to call and setup the arguments.
|
|
||||||
if (cc == eq) {
|
if (cc == eq) {
|
||||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
{
|
||||||
|
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ Push(lhs, rhs);
|
||||||
|
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||||
|
}
|
||||||
|
// Turn true into 0 and false into some non-zero value.
|
||||||
|
STATIC_ASSERT(EQUAL == 0);
|
||||||
|
__ LoadRoot(r1, Heap::kTrueValueRootIndex);
|
||||||
|
__ sub(r0, r0, r1);
|
||||||
|
__ Ret();
|
||||||
} else {
|
} else {
|
||||||
|
__ Push(lhs, rhs);
|
||||||
int ncr; // NaN compare result
|
int ncr; // NaN compare result
|
||||||
if (cc == lt || cc == le) {
|
if (cc == lt || cc == le) {
|
||||||
ncr = GREATER;
|
ncr = GREATER;
|
||||||
@ -1573,34 +1581,33 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ ldr(subject, MemOperand(sp, kSubjectOffset));
|
__ ldr(subject, MemOperand(sp, kSubjectOffset));
|
||||||
__ JumpIfSmi(subject, &runtime);
|
__ JumpIfSmi(subject, &runtime);
|
||||||
__ mov(r3, subject); // Make a copy of the original subject string.
|
__ mov(r3, subject); // Make a copy of the original subject string.
|
||||||
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
|
||||||
// subject: subject string
|
// subject: subject string
|
||||||
// r3: subject string
|
// r3: subject string
|
||||||
// r0: subject string instance type
|
|
||||||
// regexp_data: RegExp data (FixedArray)
|
// regexp_data: RegExp data (FixedArray)
|
||||||
// Handle subject string according to its encoding and representation:
|
// Handle subject string according to its encoding and representation:
|
||||||
// (1) Sequential string? If yes, go to (5).
|
// (1) Sequential string? If yes, go to (4).
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
// (3) Cons string. If the string is flat, replace subject with first string.
|
// (3) Cons string. If the string is flat, replace subject with first string
|
||||||
// Otherwise bailout.
|
// and go to (1). Otherwise bail out to runtime.
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
// (E) Carry on.
|
// (E) Carry on.
|
||||||
/// [...]
|
/// [...]
|
||||||
|
|
||||||
// Deferred code at the end of the stub:
|
// Deferred code at the end of the stub:
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
// Go to (5).
|
// Go to (4).
|
||||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
// (8) Sliced string. Replace subject with parent. Go to (1).
|
||||||
|
|
||||||
Label seq_string /* 5 */, external_string /* 7 */,
|
Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
|
||||||
check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
|
not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
|
||||||
not_long_external /* 8 */;
|
|
||||||
|
|
||||||
// (1) Sequential string? If yes, go to (5).
|
__ bind(&check_underlying);
|
||||||
|
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||||
|
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
||||||
|
|
||||||
|
// (1) Sequential string? If yes, go to (4).
|
||||||
__ and_(r1,
|
__ and_(r1,
|
||||||
r0,
|
r0,
|
||||||
Operand(kIsNotStringMask |
|
Operand(kIsNotStringMask |
|
||||||
@ -1608,15 +1615,15 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
kShortExternalStringMask),
|
kShortExternalStringMask),
|
||||||
SetCC);
|
SetCC);
|
||||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||||
__ b(eq, &seq_string); // Go to (5).
|
__ b(eq, &seq_string); // Go to (4).
|
||||||
|
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||||
__ cmp(r1, Operand(kExternalStringTag));
|
__ cmp(r1, Operand(kExternalStringTag));
|
||||||
__ b(ge, ¬_seq_nor_cons); // Go to (6).
|
__ b(ge, ¬_seq_nor_cons); // Go to (5).
|
||||||
|
|
||||||
// (3) Cons string. Check that it's flat.
|
// (3) Cons string. Check that it's flat.
|
||||||
// Replace subject with first string and reload instance type.
|
// Replace subject with first string and reload instance type.
|
||||||
@ -1624,19 +1631,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ CompareRoot(r0, Heap::kempty_stringRootIndex);
|
__ CompareRoot(r0, Heap::kempty_stringRootIndex);
|
||||||
__ b(ne, &runtime);
|
__ b(ne, &runtime);
|
||||||
__ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
__ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||||
|
__ jmp(&check_underlying);
|
||||||
|
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
__ bind(&check_underlying);
|
|
||||||
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
|
||||||
STATIC_ASSERT(kSeqStringTag == 0);
|
|
||||||
__ tst(r0, Operand(kStringRepresentationMask));
|
|
||||||
// The underlying external string is never a short external string.
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
|
||||||
__ b(ne, &external_string); // Go to (7).
|
|
||||||
|
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
__ bind(&seq_string);
|
__ bind(&seq_string);
|
||||||
// subject: sequential subject string (or look-alike, external string)
|
// subject: sequential subject string (or look-alike, external string)
|
||||||
// r3: original subject string
|
// r3: original subject string
|
||||||
@ -1869,12 +1866,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||||
|
|
||||||
// Deferred code for string handling.
|
// Deferred code for string handling.
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
__ bind(¬_seq_nor_cons);
|
__ bind(¬_seq_nor_cons);
|
||||||
// Compare flags are still set.
|
// Compare flags are still set.
|
||||||
__ b(gt, ¬_long_external); // Go to (8).
|
__ b(gt, ¬_long_external); // Go to (7).
|
||||||
|
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
__ bind(&external_string);
|
__ bind(&external_string);
|
||||||
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||||
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
||||||
@ -1891,15 +1888,15 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ sub(subject,
|
__ sub(subject,
|
||||||
subject,
|
subject,
|
||||||
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||||
__ jmp(&seq_string); // Go to (5).
|
__ jmp(&seq_string); // Go to (4).
|
||||||
|
|
||||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||||
__ bind(¬_long_external);
|
__ bind(¬_long_external);
|
||||||
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
|
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
|
||||||
__ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask));
|
__ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask));
|
||||||
__ b(ne, &runtime);
|
__ b(ne, &runtime);
|
||||||
|
|
||||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
// (8) Sliced string. Replace subject with parent. Go to (4).
|
||||||
// Load offset into r9 and replace subject string with parent.
|
// Load offset into r9 and replace subject string with parent.
|
||||||
__ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
__ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||||
__ SmiUntag(r9);
|
__ SmiUntag(r9);
|
||||||
|
90
deps/v8/src/arm64/code-stubs-arm64.cc
vendored
90
deps/v8/src/arm64/code-stubs-arm64.cc
vendored
@ -628,11 +628,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
|
|
||||||
__ Bind(&slow);
|
__ Bind(&slow);
|
||||||
|
|
||||||
__ Push(lhs, rhs);
|
|
||||||
// Figure out which native to call and setup the arguments.
|
|
||||||
if (cond == eq) {
|
if (cond == eq) {
|
||||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
{
|
||||||
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ Push(lhs, rhs);
|
||||||
|
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||||
|
}
|
||||||
|
// Turn true into 0 and false into some non-zero value.
|
||||||
|
STATIC_ASSERT(EQUAL == 0);
|
||||||
|
__ LoadRoot(x1, Heap::kTrueValueRootIndex);
|
||||||
|
__ Sub(x0, x0, x1);
|
||||||
|
__ Ret();
|
||||||
} else {
|
} else {
|
||||||
|
__ Push(lhs, rhs);
|
||||||
int ncr; // NaN compare result
|
int ncr; // NaN compare result
|
||||||
if ((cond == lt) || (cond == le)) {
|
if ((cond == lt) || (cond == le)) {
|
||||||
ncr = GREATER;
|
ncr = GREATER;
|
||||||
@ -1739,35 +1747,35 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ Peek(subject, kSubjectOffset);
|
__ Peek(subject, kSubjectOffset);
|
||||||
__ JumpIfSmi(subject, &runtime);
|
__ JumpIfSmi(subject, &runtime);
|
||||||
|
|
||||||
__ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
|
|
||||||
|
|
||||||
__ Ldr(jsstring_length, FieldMemOperand(subject, String::kLengthOffset));
|
__ Ldr(jsstring_length, FieldMemOperand(subject, String::kLengthOffset));
|
||||||
|
|
||||||
// Handle subject string according to its encoding and representation:
|
// Handle subject string according to its encoding and representation:
|
||||||
// (1) Sequential string? If yes, go to (5).
|
// (1) Sequential string? If yes, go to (4).
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
// (3) Cons string. If the string is flat, replace subject with first string.
|
// (3) Cons string. If the string is flat, replace subject with first string
|
||||||
// Otherwise bailout.
|
// and go to (1). Otherwise bail out to runtime.
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
// (E) Carry on.
|
// (E) Carry on.
|
||||||
/// [...]
|
/// [...]
|
||||||
|
|
||||||
// Deferred code at the end of the stub:
|
// Deferred code at the end of the stub:
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
// Go to (5).
|
// Go to (4).
|
||||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
// (8) Sliced string. Replace subject with parent. Go to (1).
|
||||||
|
|
||||||
Label check_underlying; // (4)
|
Label check_underlying; // (1)
|
||||||
Label seq_string; // (5)
|
Label seq_string; // (4)
|
||||||
Label not_seq_nor_cons; // (6)
|
Label not_seq_nor_cons; // (5)
|
||||||
Label external_string; // (7)
|
Label external_string; // (6)
|
||||||
Label not_long_external; // (8)
|
Label not_long_external; // (7)
|
||||||
|
|
||||||
// (1) Sequential string? If yes, go to (5).
|
__ Bind(&check_underlying);
|
||||||
|
__ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||||
|
__ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
|
||||||
|
|
||||||
|
// (1) Sequential string? If yes, go to (4).
|
||||||
__ And(string_representation,
|
__ And(string_representation,
|
||||||
string_type,
|
string_type,
|
||||||
kIsNotStringMask |
|
kIsNotStringMask |
|
||||||
@ -1784,36 +1792,24 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
// is a String
|
// is a String
|
||||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||||
STATIC_ASSERT(kShortExternalStringTag != 0);
|
STATIC_ASSERT(kShortExternalStringTag != 0);
|
||||||
__ Cbz(string_representation, &seq_string); // Go to (5).
|
__ Cbz(string_representation, &seq_string); // Go to (4).
|
||||||
|
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||||
__ Cmp(string_representation, kExternalStringTag);
|
__ Cmp(string_representation, kExternalStringTag);
|
||||||
__ B(ge, ¬_seq_nor_cons); // Go to (6).
|
__ B(ge, ¬_seq_nor_cons); // Go to (5).
|
||||||
|
|
||||||
// (3) Cons string. Check that it's flat.
|
// (3) Cons string. Check that it's flat.
|
||||||
__ Ldr(x10, FieldMemOperand(subject, ConsString::kSecondOffset));
|
__ Ldr(x10, FieldMemOperand(subject, ConsString::kSecondOffset));
|
||||||
__ JumpIfNotRoot(x10, Heap::kempty_stringRootIndex, &runtime);
|
__ JumpIfNotRoot(x10, Heap::kempty_stringRootIndex, &runtime);
|
||||||
// Replace subject with first string.
|
// Replace subject with first string.
|
||||||
__ Ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
__ Ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||||
|
__ B(&check_underlying);
|
||||||
|
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
__ Bind(&check_underlying);
|
|
||||||
// Reload the string type.
|
|
||||||
__ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
|
|
||||||
STATIC_ASSERT(kSeqStringTag == 0);
|
|
||||||
// The underlying external string is never a short external string.
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
|
||||||
__ TestAndBranchIfAnySet(string_type.X(),
|
|
||||||
kStringRepresentationMask,
|
|
||||||
&external_string); // Go to (7).
|
|
||||||
|
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
__ Bind(&seq_string);
|
__ Bind(&seq_string);
|
||||||
|
|
||||||
// Check that the third argument is a positive smi less than the subject
|
// Check that the third argument is a positive smi less than the subject
|
||||||
@ -2083,12 +2079,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||||
|
|
||||||
// Deferred code for string handling.
|
// Deferred code for string handling.
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
__ Bind(¬_seq_nor_cons);
|
__ Bind(¬_seq_nor_cons);
|
||||||
// Compare flags are still set.
|
// Compare flags are still set.
|
||||||
__ B(ne, ¬_long_external); // Go to (8).
|
__ B(ne, ¬_long_external); // Go to (7).
|
||||||
|
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
__ Bind(&external_string);
|
__ Bind(&external_string);
|
||||||
if (masm->emit_debug_code()) {
|
if (masm->emit_debug_code()) {
|
||||||
// Assert that we do not have a cons or slice (indirect strings) here.
|
// Assert that we do not have a cons or slice (indirect strings) here.
|
||||||
@ -2106,9 +2102,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
// Move the pointer so that offset-wise, it looks like a sequential string.
|
// Move the pointer so that offset-wise, it looks like a sequential string.
|
||||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||||
__ Sub(subject, subject, SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
__ Sub(subject, subject, SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
||||||
__ B(&seq_string); // Go to (5).
|
__ B(&seq_string); // Go to (4).
|
||||||
|
|
||||||
// (8) If this is a short external string or not a string, bail out to
|
// (7) If this is a short external string or not a string, bail out to
|
||||||
// runtime.
|
// runtime.
|
||||||
__ Bind(¬_long_external);
|
__ Bind(¬_long_external);
|
||||||
STATIC_ASSERT(kShortExternalStringTag != 0);
|
STATIC_ASSERT(kShortExternalStringTag != 0);
|
||||||
@ -2116,11 +2112,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
kShortExternalStringMask | kIsNotStringMask,
|
kShortExternalStringMask | kIsNotStringMask,
|
||||||
&runtime);
|
&runtime);
|
||||||
|
|
||||||
// (9) Sliced string. Replace subject with parent.
|
// (8) Sliced string. Replace subject with parent.
|
||||||
__ Ldr(sliced_string_offset,
|
__ Ldr(sliced_string_offset,
|
||||||
UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset));
|
UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||||
__ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
|
__ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
|
||||||
__ B(&check_underlying); // Go to (4).
|
__ B(&check_underlying); // Go to (1).
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,9 +530,10 @@ void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
|
|||||||
|
|
||||||
void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
|
void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
|
||||||
IA32OperandGenerator g(selector);
|
IA32OperandGenerator g(selector);
|
||||||
|
InstructionOperand temps[] = {g.TempRegister(eax)};
|
||||||
selector->Emit(opcode, g.DefineAsFixed(node, edx),
|
selector->Emit(opcode, g.DefineAsFixed(node, edx),
|
||||||
g.UseFixed(node->InputAt(0), eax),
|
g.UseFixed(node->InputAt(0), eax),
|
||||||
g.UseUnique(node->InputAt(1)));
|
g.UseUnique(node->InputAt(1)), arraysize(temps), temps);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitLea(InstructionSelector* selector, Node* result, Node* index,
|
void EmitLea(InstructionSelector* selector, Node* result, Node* index,
|
||||||
|
118
deps/v8/src/compiler/js-generic-lowering.cc
vendored
118
deps/v8/src/compiler/js-generic-lowering.cc
vendored
@ -81,117 +81,22 @@ REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV)
|
|||||||
REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
|
REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
|
||||||
#undef REPLACE_BINARY_OP_IC_CALL
|
#undef REPLACE_BINARY_OP_IC_CALL
|
||||||
|
|
||||||
|
|
||||||
// These ops are not language mode dependent; we arbitrarily pass Strength::WEAK
|
|
||||||
// here.
|
|
||||||
#define REPLACE_COMPARE_IC_CALL(op, token) \
|
|
||||||
void JSGenericLowering::Lower##op(Node* node) { \
|
|
||||||
ReplaceWithCompareIC(node, token); \
|
|
||||||
}
|
|
||||||
REPLACE_COMPARE_IC_CALL(JSEqual, Token::EQ)
|
|
||||||
REPLACE_COMPARE_IC_CALL(JSNotEqual, Token::NE)
|
|
||||||
REPLACE_COMPARE_IC_CALL(JSStrictEqual, Token::EQ_STRICT)
|
|
||||||
REPLACE_COMPARE_IC_CALL(JSStrictNotEqual, Token::NE_STRICT)
|
|
||||||
REPLACE_COMPARE_IC_CALL(JSLessThan, Token::LT)
|
|
||||||
REPLACE_COMPARE_IC_CALL(JSGreaterThan, Token::GT)
|
|
||||||
REPLACE_COMPARE_IC_CALL(JSLessThanOrEqual, Token::LTE)
|
|
||||||
REPLACE_COMPARE_IC_CALL(JSGreaterThanOrEqual, Token::GTE)
|
|
||||||
#undef REPLACE_COMPARE_IC_CALL
|
|
||||||
|
|
||||||
|
|
||||||
#define REPLACE_RUNTIME_CALL(op, fun) \
|
#define REPLACE_RUNTIME_CALL(op, fun) \
|
||||||
void JSGenericLowering::Lower##op(Node* node) { \
|
void JSGenericLowering::Lower##op(Node* node) { \
|
||||||
ReplaceWithRuntimeCall(node, fun); \
|
ReplaceWithRuntimeCall(node, fun); \
|
||||||
}
|
}
|
||||||
|
REPLACE_RUNTIME_CALL(JSEqual, Runtime::kEqual)
|
||||||
|
REPLACE_RUNTIME_CALL(JSNotEqual, Runtime::kNotEqual)
|
||||||
|
REPLACE_RUNTIME_CALL(JSStrictEqual, Runtime::kStrictEqual)
|
||||||
|
REPLACE_RUNTIME_CALL(JSStrictNotEqual, Runtime::kStrictNotEqual)
|
||||||
|
REPLACE_RUNTIME_CALL(JSLessThan, Runtime::kLessThan)
|
||||||
|
REPLACE_RUNTIME_CALL(JSGreaterThan, Runtime::kGreaterThan)
|
||||||
|
REPLACE_RUNTIME_CALL(JSLessThanOrEqual, Runtime::kLessThanOrEqual)
|
||||||
|
REPLACE_RUNTIME_CALL(JSGreaterThanOrEqual, Runtime::kGreaterThanOrEqual)
|
||||||
REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
|
REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
|
||||||
REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
|
REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
|
||||||
REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
|
REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
|
||||||
#undef REPLACE_RUNTIME
|
#undef REPLACE_RUNTIME_CALL
|
||||||
|
|
||||||
|
|
||||||
static CallDescriptor::Flags FlagsForNode(Node* node) {
|
|
||||||
CallDescriptor::Flags result = CallDescriptor::kNoFlags;
|
|
||||||
if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
|
|
||||||
result |= CallDescriptor::kNeedsFrameState;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) {
|
|
||||||
Callable callable = CodeFactory::CompareIC(isolate(), token);
|
|
||||||
|
|
||||||
// Create a new call node asking a CompareIC for help.
|
|
||||||
NodeVector inputs(zone());
|
|
||||||
inputs.reserve(node->InputCount() + 1);
|
|
||||||
inputs.push_back(jsgraph()->HeapConstant(callable.code()));
|
|
||||||
inputs.push_back(NodeProperties::GetValueInput(node, 0));
|
|
||||||
inputs.push_back(NodeProperties::GetValueInput(node, 1));
|
|
||||||
inputs.push_back(NodeProperties::GetContextInput(node));
|
|
||||||
// Some comparisons (StrictEqual) don't have an effect, control or frame
|
|
||||||
// state inputs, so handle those cases here.
|
|
||||||
if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
|
|
||||||
inputs.push_back(NodeProperties::GetFrameStateInput(node, 0));
|
|
||||||
}
|
|
||||||
Node* effect = (node->op()->EffectInputCount() > 0)
|
|
||||||
? NodeProperties::GetEffectInput(node)
|
|
||||||
: graph()->start();
|
|
||||||
inputs.push_back(effect);
|
|
||||||
Node* control = (node->op()->ControlInputCount() > 0)
|
|
||||||
? NodeProperties::GetControlInput(node)
|
|
||||||
: graph()->start();
|
|
||||||
inputs.push_back(control);
|
|
||||||
CallDescriptor* desc_compare = Linkage::GetStubCallDescriptor(
|
|
||||||
isolate(), zone(), callable.descriptor(), 0,
|
|
||||||
CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node),
|
|
||||||
Operator::kNoProperties, MachineType::IntPtr());
|
|
||||||
Node* compare =
|
|
||||||
graph()->NewNode(common()->Call(desc_compare),
|
|
||||||
static_cast<int>(inputs.size()), &inputs.front());
|
|
||||||
|
|
||||||
// Decide how the return value from the above CompareIC can be converted into
|
|
||||||
// a JavaScript boolean oddball depending on the given token.
|
|
||||||
Node* false_value = jsgraph()->FalseConstant();
|
|
||||||
Node* true_value = jsgraph()->TrueConstant();
|
|
||||||
const Operator* op = nullptr;
|
|
||||||
switch (token) {
|
|
||||||
case Token::EQ: // a == 0
|
|
||||||
case Token::EQ_STRICT:
|
|
||||||
op = machine()->WordEqual();
|
|
||||||
break;
|
|
||||||
case Token::NE: // a != 0 becomes !(a == 0)
|
|
||||||
case Token::NE_STRICT:
|
|
||||||
op = machine()->WordEqual();
|
|
||||||
std::swap(true_value, false_value);
|
|
||||||
break;
|
|
||||||
case Token::LT: // a < 0
|
|
||||||
op = machine()->IntLessThan();
|
|
||||||
break;
|
|
||||||
case Token::GT: // a > 0 becomes !(a <= 0)
|
|
||||||
op = machine()->IntLessThanOrEqual();
|
|
||||||
std::swap(true_value, false_value);
|
|
||||||
break;
|
|
||||||
case Token::LTE: // a <= 0
|
|
||||||
op = machine()->IntLessThanOrEqual();
|
|
||||||
break;
|
|
||||||
case Token::GTE: // a >= 0 becomes !(a < 0)
|
|
||||||
op = machine()->IntLessThan();
|
|
||||||
std::swap(true_value, false_value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
Node* booleanize = graph()->NewNode(op, compare, jsgraph()->ZeroConstant());
|
|
||||||
|
|
||||||
// Finally patch the original node to select a boolean.
|
|
||||||
NodeProperties::ReplaceUses(node, node, compare, compare, compare);
|
|
||||||
node->TrimInputCount(3);
|
|
||||||
node->ReplaceInput(0, booleanize);
|
|
||||||
node->ReplaceInput(1, true_value);
|
|
||||||
node->ReplaceInput(2, false_value);
|
|
||||||
NodeProperties::ChangeOp(node,
|
|
||||||
common()->Select(MachineRepresentation::kTagged));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
|
void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
|
||||||
CallDescriptor::Flags flags) {
|
CallDescriptor::Flags flags) {
|
||||||
@ -207,11 +112,12 @@ void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
|
|||||||
void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
|
void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
|
||||||
Runtime::FunctionId f,
|
Runtime::FunctionId f,
|
||||||
int nargs_override) {
|
int nargs_override) {
|
||||||
|
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
|
||||||
Operator::Properties properties = node->op()->properties();
|
Operator::Properties properties = node->op()->properties();
|
||||||
const Runtime::Function* fun = Runtime::FunctionForId(f);
|
const Runtime::Function* fun = Runtime::FunctionForId(f);
|
||||||
int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
|
int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
|
||||||
CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
|
CallDescriptor* desc =
|
||||||
zone(), f, nargs, properties, CallDescriptor::kNeedsFrameState);
|
Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
|
||||||
Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
|
Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
|
||||||
Node* arity = jsgraph()->Int32Constant(nargs);
|
Node* arity = jsgraph()->Int32Constant(nargs);
|
||||||
node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
|
node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
|
||||||
|
1
deps/v8/src/compiler/js-generic-lowering.h
vendored
1
deps/v8/src/compiler/js-generic-lowering.h
vendored
@ -36,7 +36,6 @@ class JSGenericLowering final : public Reducer {
|
|||||||
#undef DECLARE_LOWER
|
#undef DECLARE_LOWER
|
||||||
|
|
||||||
// Helpers to replace existing nodes with a generic call.
|
// Helpers to replace existing nodes with a generic call.
|
||||||
void ReplaceWithCompareIC(Node* node, Token::Value token);
|
|
||||||
void ReplaceWithStubCall(Node* node, Callable c, CallDescriptor::Flags flags);
|
void ReplaceWithStubCall(Node* node, Callable c, CallDescriptor::Flags flags);
|
||||||
void ReplaceWithRuntimeCall(Node* node, Runtime::FunctionId f, int args = -1);
|
void ReplaceWithRuntimeCall(Node* node, Runtime::FunctionId f, int args = -1);
|
||||||
|
|
||||||
|
@ -763,9 +763,10 @@ void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
|
|||||||
|
|
||||||
void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
|
void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
|
||||||
X64OperandGenerator g(selector);
|
X64OperandGenerator g(selector);
|
||||||
selector->Emit(opcode, g.DefineAsFixed(node, rdx),
|
InstructionOperand temps[] = {g.TempRegister(rax)};
|
||||||
g.UseFixed(node->InputAt(0), rax),
|
selector->Emit(
|
||||||
g.UseUniqueRegister(node->InputAt(1)));
|
opcode, g.DefineAsFixed(node, rdx), g.UseFixed(node->InputAt(0), rax),
|
||||||
|
g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
1
deps/v8/src/debug/debug-evaluate.cc
vendored
1
deps/v8/src/debug/debug-evaluate.cc
vendored
@ -346,6 +346,7 @@ void DebugEvaluate::ContextBuilder::MaterializeContextChain(
|
|||||||
// within debug-evaluate.
|
// within debug-evaluate.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (value->IsTheHole()) continue; // Value is not initialized yet (in TDZ).
|
||||||
JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
|
JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
100
deps/v8/src/ia32/code-stubs-ia32.cc
vendored
100
deps/v8/src/ia32/code-stubs-ia32.cc
vendored
@ -798,39 +798,37 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ mov(eax, Operand(esp, kSubjectOffset));
|
__ mov(eax, Operand(esp, kSubjectOffset));
|
||||||
__ JumpIfSmi(eax, &runtime);
|
__ JumpIfSmi(eax, &runtime);
|
||||||
__ mov(edx, eax); // Make a copy of the original subject string.
|
__ mov(edx, eax); // Make a copy of the original subject string.
|
||||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
|
||||||
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
|
||||||
|
|
||||||
// eax: subject string
|
// eax: subject string
|
||||||
// edx: subject string
|
// edx: subject string
|
||||||
// ebx: subject string instance type
|
|
||||||
// ecx: RegExp data (FixedArray)
|
// ecx: RegExp data (FixedArray)
|
||||||
// Handle subject string according to its encoding and representation:
|
// Handle subject string according to its encoding and representation:
|
||||||
// (1) Sequential two byte? If yes, go to (9).
|
// (1) Sequential two byte? If yes, go to (9).
|
||||||
// (2) Sequential one byte? If yes, go to (6).
|
// (2) Sequential one byte? If yes, go to (5).
|
||||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
// (3) Sequential or cons? If not, go to (6).
|
||||||
// (4) Cons string. If the string is flat, replace subject with first string.
|
// (4) Cons string. If the string is flat, replace subject with first string
|
||||||
// Otherwise bailout.
|
// and go to (1). Otherwise bail out to runtime.
|
||||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
// (5) One byte sequential. Load regexp code for one byte.
|
||||||
// (5b) Is subject external? If yes, go to (8).
|
|
||||||
// (6) One byte sequential. Load regexp code for one byte.
|
|
||||||
// (E) Carry on.
|
// (E) Carry on.
|
||||||
/// [...]
|
/// [...]
|
||||||
|
|
||||||
// Deferred code at the end of the stub:
|
// Deferred code at the end of the stub:
|
||||||
// (7) Not a long external string? If yes, go to (10).
|
// (6) Long external string? If not, go to (10).
|
||||||
// (8) External string. Make it, offset-wise, look like a sequential string.
|
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||||
// (8a) Is the external string one byte? If yes, go to (6).
|
// (8) Is the external string one byte? If yes, go to (5).
|
||||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||||
// (10) Short external string or not a string? If yes, bail out to runtime.
|
// (10) Short external string or not a string? If yes, bail out to runtime.
|
||||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||||
|
|
||||||
Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
|
Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
|
||||||
external_string /* 8 */, check_underlying /* 5a */,
|
external_string /* 7 */, check_underlying /* 1 */,
|
||||||
not_seq_nor_cons /* 7 */, check_code /* E */,
|
not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
|
||||||
not_long_external /* 10 */;
|
|
||||||
|
|
||||||
|
__ bind(&check_underlying);
|
||||||
// (1) Sequential two byte? If yes, go to (9).
|
// (1) Sequential two byte? If yes, go to (9).
|
||||||
|
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||||
|
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
||||||
|
|
||||||
__ and_(ebx, kIsNotStringMask |
|
__ and_(ebx, kIsNotStringMask |
|
||||||
kStringRepresentationMask |
|
kStringRepresentationMask |
|
||||||
kStringEncodingMask |
|
kStringEncodingMask |
|
||||||
@ -838,14 +836,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
||||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
__ j(zero, &seq_two_byte_string); // Go to (9).
|
||||||
|
|
||||||
// (2) Sequential one byte? If yes, go to (6).
|
// (2) Sequential one byte? If yes, go to (5).
|
||||||
// Any other sequential string must be one byte.
|
// Any other sequential string must be one byte.
|
||||||
__ and_(ebx, Immediate(kIsNotStringMask |
|
__ and_(ebx, Immediate(kIsNotStringMask |
|
||||||
kStringRepresentationMask |
|
kStringRepresentationMask |
|
||||||
kShortExternalStringMask));
|
kShortExternalStringMask));
|
||||||
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6).
|
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
|
||||||
|
|
||||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
// (3) Sequential or cons? If not, go to (6).
|
||||||
// We check whether the subject string is a cons, since sequential strings
|
// We check whether the subject string is a cons, since sequential strings
|
||||||
// have already been covered.
|
// have already been covered.
|
||||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||||
@ -853,32 +851,19 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||||
__ cmp(ebx, Immediate(kExternalStringTag));
|
__ cmp(ebx, Immediate(kExternalStringTag));
|
||||||
__ j(greater_equal, ¬_seq_nor_cons); // Go to (7).
|
__ j(greater_equal, ¬_seq_nor_cons); // Go to (6).
|
||||||
|
|
||||||
// (4) Cons string. Check that it's flat.
|
// (4) Cons string. Check that it's flat.
|
||||||
// Replace subject with first string and reload instance type.
|
// Replace subject with first string and reload instance type.
|
||||||
__ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
|
__ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
|
||||||
__ j(not_equal, &runtime);
|
__ j(not_equal, &runtime);
|
||||||
__ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
|
__ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
|
||||||
__ bind(&check_underlying);
|
__ jmp(&check_underlying);
|
||||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
|
||||||
__ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
|
||||||
|
|
||||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
|
||||||
__ test_b(ebx, kStringRepresentationMask | kStringEncodingMask);
|
|
||||||
STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
|
|
||||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
|
||||||
// (5b) Is subject external? If yes, go to (8).
|
|
||||||
__ test_b(ebx, kStringRepresentationMask);
|
|
||||||
// The underlying external string is never a short external string.
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
|
||||||
__ j(not_zero, &external_string); // Go to (8).
|
|
||||||
|
|
||||||
// eax: sequential subject string (or look-alike, external string)
|
// eax: sequential subject string (or look-alike, external string)
|
||||||
// edx: original subject string
|
// edx: original subject string
|
||||||
// ecx: RegExp data (FixedArray)
|
// ecx: RegExp data (FixedArray)
|
||||||
// (6) One byte sequential. Load regexp code for one byte.
|
// (5) One byte sequential. Load regexp code for one byte.
|
||||||
__ bind(&seq_one_byte_string);
|
__ bind(&seq_one_byte_string);
|
||||||
// Load previous index and check range before edx is overwritten. We have
|
// Load previous index and check range before edx is overwritten. We have
|
||||||
// to use edx instead of eax here because it might have been only made to
|
// to use edx instead of eax here because it might have been only made to
|
||||||
@ -1105,12 +1090,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||||
|
|
||||||
// Deferred code for string handling.
|
// Deferred code for string handling.
|
||||||
// (7) Not a long external string? If yes, go to (10).
|
// (6) Long external string? If not, go to (10).
|
||||||
__ bind(¬_seq_nor_cons);
|
__ bind(¬_seq_nor_cons);
|
||||||
// Compare flags are still set from (3).
|
// Compare flags are still set from (3).
|
||||||
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
|
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
|
||||||
|
|
||||||
// (8) External string. Short external strings have been ruled out.
|
// (7) External string. Short external strings have been ruled out.
|
||||||
__ bind(&external_string);
|
__ bind(&external_string);
|
||||||
// Reload instance type.
|
// Reload instance type.
|
||||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||||
@ -1126,14 +1111,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||||
__ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
__ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||||
// (8a) Is the external string one byte? If yes, go to (6).
|
// (8) Is the external string one byte? If yes, go to (5).
|
||||||
__ test_b(ebx, kStringEncodingMask);
|
__ test_b(ebx, kStringEncodingMask);
|
||||||
__ j(not_zero, &seq_one_byte_string); // Goto (6).
|
__ j(not_zero, &seq_one_byte_string); // Go to (5).
|
||||||
|
|
||||||
// eax: sequential subject string (or look-alike, external string)
|
// eax: sequential subject string (or look-alike, external string)
|
||||||
// edx: original subject string
|
// edx: original subject string
|
||||||
// ecx: RegExp data (FixedArray)
|
// ecx: RegExp data (FixedArray)
|
||||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||||
__ bind(&seq_two_byte_string);
|
__ bind(&seq_two_byte_string);
|
||||||
// Load previous index and check range before edx is overwritten. We have
|
// Load previous index and check range before edx is overwritten. We have
|
||||||
// to use edx instead of eax here because it might have been only made to
|
// to use edx instead of eax here because it might have been only made to
|
||||||
@ -1153,11 +1138,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
|
__ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
|
||||||
__ j(not_zero, &runtime);
|
__ j(not_zero, &runtime);
|
||||||
|
|
||||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||||
// Load offset into edi and replace subject string with parent.
|
// Load offset into edi and replace subject string with parent.
|
||||||
__ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
|
__ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
|
||||||
__ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
|
__ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
|
||||||
__ jmp(&check_underlying); // Go to (5a).
|
__ jmp(&check_underlying); // Go to (1).
|
||||||
#endif // V8_INTERPRETED_REGEXP
|
#endif // V8_INTERPRETED_REGEXP
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1442,21 +1427,24 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
__ bind(&runtime_call);
|
__ bind(&runtime_call);
|
||||||
|
|
||||||
// Push arguments below the return address.
|
|
||||||
__ pop(ecx);
|
|
||||||
__ push(edx);
|
|
||||||
__ push(eax);
|
|
||||||
|
|
||||||
// Figure out which native to call and setup the arguments.
|
|
||||||
if (cc == equal) {
|
if (cc == equal) {
|
||||||
__ push(ecx);
|
{
|
||||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ Push(edx);
|
||||||
|
__ Push(eax);
|
||||||
|
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||||
|
}
|
||||||
|
// Turn true into 0 and false into some non-zero value.
|
||||||
|
STATIC_ASSERT(EQUAL == 0);
|
||||||
|
__ sub(eax, Immediate(isolate()->factory()->true_value()));
|
||||||
|
__ Ret();
|
||||||
} else {
|
} else {
|
||||||
|
// Push arguments below the return address.
|
||||||
|
__ pop(ecx);
|
||||||
|
__ push(edx);
|
||||||
|
__ push(eax);
|
||||||
__ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
|
__ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
|
||||||
|
|
||||||
// Restore return address on the stack.
|
|
||||||
__ push(ecx);
|
__ push(ecx);
|
||||||
|
|
||||||
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
|
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
|
||||||
// tagged as a small integer.
|
// tagged as a small integer.
|
||||||
__ TailCallRuntime(Runtime::kCompare);
|
__ TailCallRuntime(Runtime::kCompare);
|
||||||
|
30
deps/v8/src/ic/ic.cc
vendored
30
deps/v8/src/ic/ic.cc
vendored
@ -573,13 +573,21 @@ static bool MigrateDeprecated(Handle<Object> object) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
|
||||||
void IC::ConfigureVectorState(IC::State new_state) {
|
|
||||||
DCHECK(UseVector());
|
DCHECK(UseVector());
|
||||||
if (new_state == PREMONOMORPHIC) {
|
if (new_state == PREMONOMORPHIC) {
|
||||||
nexus()->ConfigurePremonomorphic();
|
nexus()->ConfigurePremonomorphic();
|
||||||
} else if (new_state == MEGAMORPHIC) {
|
} else if (new_state == MEGAMORPHIC) {
|
||||||
nexus()->ConfigureMegamorphic();
|
if (kind() == Code::LOAD_IC || kind() == Code::STORE_IC) {
|
||||||
|
nexus()->ConfigureMegamorphic();
|
||||||
|
} else if (kind() == Code::KEYED_LOAD_IC) {
|
||||||
|
KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
|
||||||
|
nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
|
||||||
|
} else {
|
||||||
|
DCHECK(kind() == Code::KEYED_STORE_IC);
|
||||||
|
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
|
||||||
|
nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -662,7 +670,7 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
|
|||||||
// Rewrite to the generic keyed load stub.
|
// Rewrite to the generic keyed load stub.
|
||||||
if (FLAG_use_ic) {
|
if (FLAG_use_ic) {
|
||||||
DCHECK(UseVector());
|
DCHECK(UseVector());
|
||||||
ConfigureVectorState(MEGAMORPHIC);
|
ConfigureVectorState(MEGAMORPHIC, name);
|
||||||
TRACE_IC("LoadIC", name);
|
TRACE_IC("LoadIC", name);
|
||||||
TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
|
TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
|
||||||
}
|
}
|
||||||
@ -853,7 +861,7 @@ void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
|
|||||||
CopyICToMegamorphicCache(name);
|
CopyICToMegamorphicCache(name);
|
||||||
}
|
}
|
||||||
if (UseVector()) {
|
if (UseVector()) {
|
||||||
ConfigureVectorState(MEGAMORPHIC);
|
ConfigureVectorState(MEGAMORPHIC, name);
|
||||||
} else {
|
} else {
|
||||||
set_target(*megamorphic_stub());
|
set_target(*megamorphic_stub());
|
||||||
}
|
}
|
||||||
@ -1012,7 +1020,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
|
|||||||
if (state() == UNINITIALIZED) {
|
if (state() == UNINITIALIZED) {
|
||||||
// This is the first time we execute this inline cache. Set the target to
|
// This is the first time we execute this inline cache. Set the target to
|
||||||
// the pre monomorphic stub to delay setting the monomorphic state.
|
// the pre monomorphic stub to delay setting the monomorphic state.
|
||||||
ConfigureVectorState(PREMONOMORPHIC);
|
ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
|
||||||
TRACE_IC("LoadIC", lookup->name());
|
TRACE_IC("LoadIC", lookup->name());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1378,7 +1386,7 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
|
|||||||
if (!is_vector_set() || stub.is_null()) {
|
if (!is_vector_set() || stub.is_null()) {
|
||||||
Code* generic = *megamorphic_stub();
|
Code* generic = *megamorphic_stub();
|
||||||
if (!stub.is_null() && *stub == generic) {
|
if (!stub.is_null() && *stub == generic) {
|
||||||
ConfigureVectorState(MEGAMORPHIC);
|
ConfigureVectorState(MEGAMORPHIC, key);
|
||||||
TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
|
TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1471,7 +1479,7 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
|
|||||||
// Rewrite to the generic keyed store stub.
|
// Rewrite to the generic keyed store stub.
|
||||||
if (FLAG_use_ic) {
|
if (FLAG_use_ic) {
|
||||||
if (UseVector()) {
|
if (UseVector()) {
|
||||||
ConfigureVectorState(MEGAMORPHIC);
|
ConfigureVectorState(MEGAMORPHIC, name);
|
||||||
} else if (!AddressIsDeoptimizedCode()) {
|
} else if (!AddressIsDeoptimizedCode()) {
|
||||||
set_target(*megamorphic_stub());
|
set_target(*megamorphic_stub());
|
||||||
}
|
}
|
||||||
@ -1645,7 +1653,7 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
|
|||||||
if (state() == UNINITIALIZED) {
|
if (state() == UNINITIALIZED) {
|
||||||
// This is the first time we execute this inline cache. Set the target to
|
// This is the first time we execute this inline cache. Set the target to
|
||||||
// the pre monomorphic stub to delay setting the monomorphic state.
|
// the pre monomorphic stub to delay setting the monomorphic state.
|
||||||
ConfigureVectorState(PREMONOMORPHIC);
|
ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
|
||||||
TRACE_IC("StoreIC", lookup->name());
|
TRACE_IC("StoreIC", lookup->name());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2072,7 +2080,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
|
|||||||
JSReceiver::MAY_BE_STORE_FROM_KEYED),
|
JSReceiver::MAY_BE_STORE_FROM_KEYED),
|
||||||
Object);
|
Object);
|
||||||
if (!is_vector_set()) {
|
if (!is_vector_set()) {
|
||||||
ConfigureVectorState(MEGAMORPHIC);
|
ConfigureVectorState(MEGAMORPHIC, key);
|
||||||
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
|
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
|
||||||
"unhandled internalized string key");
|
"unhandled internalized string key");
|
||||||
TRACE_IC("StoreIC", key);
|
TRACE_IC("StoreIC", key);
|
||||||
@ -2147,7 +2155,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
|
|||||||
if (!is_vector_set() || stub.is_null()) {
|
if (!is_vector_set() || stub.is_null()) {
|
||||||
Code* megamorphic = *megamorphic_stub();
|
Code* megamorphic = *megamorphic_stub();
|
||||||
if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) {
|
if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) {
|
||||||
ConfigureVectorState(MEGAMORPHIC);
|
ConfigureVectorState(MEGAMORPHIC, key);
|
||||||
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
|
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
|
||||||
*stub == megamorphic ? "set generic" : "slow stub");
|
*stub == megamorphic ? "set generic" : "slow stub");
|
||||||
}
|
}
|
||||||
|
20
deps/v8/src/ic/ic.h
vendored
20
deps/v8/src/ic/ic.h
vendored
@ -112,7 +112,7 @@ class IC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Configure for most states.
|
// Configure for most states.
|
||||||
void ConfigureVectorState(IC::State new_state);
|
void ConfigureVectorState(IC::State new_state, Handle<Object> key);
|
||||||
// Configure the vector for MONOMORPHIC.
|
// Configure the vector for MONOMORPHIC.
|
||||||
void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
|
void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
|
||||||
Handle<Code> handler);
|
Handle<Code> handler);
|
||||||
@ -296,10 +296,6 @@ class CallIC : public IC {
|
|||||||
|
|
||||||
class LoadIC : public IC {
|
class LoadIC : public IC {
|
||||||
public:
|
public:
|
||||||
static ExtraICState ComputeExtraICState(TypeofMode typeof_mode) {
|
|
||||||
return LoadICState(typeof_mode).GetExtraICState();
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeofMode typeof_mode() const {
|
TypeofMode typeof_mode() const {
|
||||||
return LoadICState::GetTypeofMode(extra_ic_state());
|
return LoadICState::GetTypeofMode(extra_ic_state());
|
||||||
}
|
}
|
||||||
@ -364,20 +360,6 @@ class LoadIC : public IC {
|
|||||||
|
|
||||||
class KeyedLoadIC : public LoadIC {
|
class KeyedLoadIC : public LoadIC {
|
||||||
public:
|
public:
|
||||||
// ExtraICState bits (building on IC)
|
|
||||||
class IcCheckTypeField
|
|
||||||
: public BitField<IcCheckType, LoadICState::kNextBitFieldOffset, 1> {};
|
|
||||||
|
|
||||||
static ExtraICState ComputeExtraICState(TypeofMode typeof_mode,
|
|
||||||
IcCheckType key_type) {
|
|
||||||
return LoadICState(typeof_mode).GetExtraICState() |
|
|
||||||
IcCheckTypeField::encode(key_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static IcCheckType GetKeyType(ExtraICState extra_state) {
|
|
||||||
return IcCheckTypeField::decode(extra_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyedLoadIC(FrameDepth depth, Isolate* isolate,
|
KeyedLoadIC(FrameDepth depth, Isolate* isolate,
|
||||||
KeyedLoadICNexus* nexus = NULL)
|
KeyedLoadICNexus* nexus = NULL)
|
||||||
: LoadIC(depth, isolate, nexus) {
|
: LoadIC(depth, isolate, nexus) {
|
||||||
|
16
deps/v8/src/interpreter/interpreter.cc
vendored
16
deps/v8/src/interpreter/interpreter.cc
vendored
@ -1139,7 +1139,7 @@ void Interpreter::DoNewWide(InterpreterAssembler* assembler) {
|
|||||||
//
|
//
|
||||||
// Test if the value in the <src> register equals the accumulator.
|
// Test if the value in the <src> register equals the accumulator.
|
||||||
void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
|
void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
|
||||||
DoBinaryOp(Runtime::kInterpreterEquals, assembler);
|
DoBinaryOp(Runtime::kEqual, assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1147,7 +1147,7 @@ void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
|
|||||||
//
|
//
|
||||||
// Test if the value in the <src> register is not equal to the accumulator.
|
// Test if the value in the <src> register is not equal to the accumulator.
|
||||||
void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
|
void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
|
||||||
DoBinaryOp(Runtime::kInterpreterNotEquals, assembler);
|
DoBinaryOp(Runtime::kNotEqual, assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1155,7 +1155,7 @@ void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
|
|||||||
//
|
//
|
||||||
// Test if the value in the <src> register is strictly equal to the accumulator.
|
// Test if the value in the <src> register is strictly equal to the accumulator.
|
||||||
void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
|
void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
|
||||||
DoBinaryOp(Runtime::kInterpreterStrictEquals, assembler);
|
DoBinaryOp(Runtime::kStrictEqual, assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1164,7 +1164,7 @@ void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
|
|||||||
// Test if the value in the <src> register is not strictly equal to the
|
// Test if the value in the <src> register is not strictly equal to the
|
||||||
// accumulator.
|
// accumulator.
|
||||||
void Interpreter::DoTestNotEqualStrict(InterpreterAssembler* assembler) {
|
void Interpreter::DoTestNotEqualStrict(InterpreterAssembler* assembler) {
|
||||||
DoBinaryOp(Runtime::kInterpreterStrictNotEquals, assembler);
|
DoBinaryOp(Runtime::kStrictNotEqual, assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1172,7 +1172,7 @@ void Interpreter::DoTestNotEqualStrict(InterpreterAssembler* assembler) {
|
|||||||
//
|
//
|
||||||
// Test if the value in the <src> register is less than the accumulator.
|
// Test if the value in the <src> register is less than the accumulator.
|
||||||
void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
|
void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
|
||||||
DoBinaryOp(Runtime::kInterpreterLessThan, assembler);
|
DoBinaryOp(Runtime::kLessThan, assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1180,7 +1180,7 @@ void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
|
|||||||
//
|
//
|
||||||
// Test if the value in the <src> register is greater than the accumulator.
|
// Test if the value in the <src> register is greater than the accumulator.
|
||||||
void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
|
void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
|
||||||
DoBinaryOp(Runtime::kInterpreterGreaterThan, assembler);
|
DoBinaryOp(Runtime::kGreaterThan, assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1189,7 +1189,7 @@ void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
|
|||||||
// Test if the value in the <src> register is less than or equal to the
|
// Test if the value in the <src> register is less than or equal to the
|
||||||
// accumulator.
|
// accumulator.
|
||||||
void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
|
void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
|
||||||
DoBinaryOp(Runtime::kInterpreterLessThanOrEqual, assembler);
|
DoBinaryOp(Runtime::kLessThanOrEqual, assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1198,7 +1198,7 @@ void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
|
|||||||
// Test if the value in the <src> register is greater than or equal to the
|
// Test if the value in the <src> register is greater than or equal to the
|
||||||
// accumulator.
|
// accumulator.
|
||||||
void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) {
|
void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) {
|
||||||
DoBinaryOp(Runtime::kInterpreterGreaterThanOrEqual, assembler);
|
DoBinaryOp(Runtime::kGreaterThanOrEqual, assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
2
deps/v8/src/isolate.cc
vendored
2
deps/v8/src/isolate.cc
vendored
@ -2512,6 +2512,7 @@ bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Isolate::IsArraySpeciesLookupChainIntact() {
|
bool Isolate::IsArraySpeciesLookupChainIntact() {
|
||||||
|
if (!FLAG_harmony_species) return true;
|
||||||
// Note: It would be nice to have debug checks to make sure that the
|
// Note: It would be nice to have debug checks to make sure that the
|
||||||
// species protector is accurate, but this would be hard to do for most of
|
// species protector is accurate, but this would be hard to do for most of
|
||||||
// what the protector stands for:
|
// what the protector stands for:
|
||||||
@ -2530,6 +2531,7 @@ bool Isolate::IsArraySpeciesLookupChainIntact() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Isolate::InvalidateArraySpeciesProtector() {
|
void Isolate::InvalidateArraySpeciesProtector() {
|
||||||
|
if (!FLAG_harmony_species) return;
|
||||||
DCHECK(factory()->species_protector()->value()->IsSmi());
|
DCHECK(factory()->species_protector()->value()->IsSmi());
|
||||||
DCHECK(IsArraySpeciesLookupChainIntact());
|
DCHECK(IsArraySpeciesLookupChainIntact());
|
||||||
PropertyCell::SetValueWithInvalidation(
|
PropertyCell::SetValueWithInvalidation(
|
||||||
|
85
deps/v8/src/mips/code-stubs-mips.cc
vendored
85
deps/v8/src/mips/code-stubs-mips.cc
vendored
@ -718,13 +718,21 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
// Never falls through to here.
|
// Never falls through to here.
|
||||||
|
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
// Prepare for call to builtin. Push object pointers, a0 (lhs) first,
|
|
||||||
// a1 (rhs) second.
|
|
||||||
__ Push(lhs, rhs);
|
|
||||||
// Figure out which native to call and setup the arguments.
|
|
||||||
if (cc == eq) {
|
if (cc == eq) {
|
||||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
{
|
||||||
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ Push(lhs, rhs);
|
||||||
|
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||||
|
}
|
||||||
|
// Turn true into 0 and false into some non-zero value.
|
||||||
|
STATIC_ASSERT(EQUAL == 0);
|
||||||
|
__ LoadRoot(a0, Heap::kTrueValueRootIndex);
|
||||||
|
__ Ret(USE_DELAY_SLOT);
|
||||||
|
__ subu(v0, v0, a0); // In delay slot.
|
||||||
} else {
|
} else {
|
||||||
|
// Prepare for call to builtin. Push object pointers, a0 (lhs) first,
|
||||||
|
// a1 (rhs) second.
|
||||||
|
__ Push(lhs, rhs);
|
||||||
int ncr; // NaN compare result.
|
int ncr; // NaN compare result.
|
||||||
if (cc == lt || cc == le) {
|
if (cc == lt || cc == le) {
|
||||||
ncr = GREATER;
|
ncr = GREATER;
|
||||||
@ -1597,7 +1605,6 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
|
|||||||
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
|
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpExecStub::Generate(MacroAssembler* masm) {
|
void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||||
// Just jump directly to runtime if native RegExp is not selected at compile
|
// Just jump directly to runtime if native RegExp is not selected at compile
|
||||||
// time or if regexp entry in generated code is turned off runtime switch or
|
// time or if regexp entry in generated code is turned off runtime switch or
|
||||||
@ -1630,8 +1637,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
|
|
||||||
// Ensure that a RegExp stack is allocated.
|
// Ensure that a RegExp stack is allocated.
|
||||||
ExternalReference address_of_regexp_stack_memory_address =
|
ExternalReference address_of_regexp_stack_memory_address =
|
||||||
ExternalReference::address_of_regexp_stack_memory_address(
|
ExternalReference::address_of_regexp_stack_memory_address(isolate());
|
||||||
isolate());
|
|
||||||
ExternalReference address_of_regexp_stack_memory_size =
|
ExternalReference address_of_regexp_stack_memory_size =
|
||||||
ExternalReference::address_of_regexp_stack_memory_size(isolate());
|
ExternalReference::address_of_regexp_stack_memory_size(isolate());
|
||||||
__ li(a0, Operand(address_of_regexp_stack_memory_size));
|
__ li(a0, Operand(address_of_regexp_stack_memory_size));
|
||||||
@ -1683,34 +1689,33 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ lw(subject, MemOperand(sp, kSubjectOffset));
|
__ lw(subject, MemOperand(sp, kSubjectOffset));
|
||||||
__ JumpIfSmi(subject, &runtime);
|
__ JumpIfSmi(subject, &runtime);
|
||||||
__ mov(a3, subject); // Make a copy of the original subject string.
|
__ mov(a3, subject); // Make a copy of the original subject string.
|
||||||
__ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
|
||||||
// subject: subject string
|
// subject: subject string
|
||||||
// a3: subject string
|
// a3: subject string
|
||||||
// a0: subject string instance type
|
|
||||||
// regexp_data: RegExp data (FixedArray)
|
// regexp_data: RegExp data (FixedArray)
|
||||||
// Handle subject string according to its encoding and representation:
|
// Handle subject string according to its encoding and representation:
|
||||||
// (1) Sequential string? If yes, go to (5).
|
// (1) Sequential string? If yes, go to (4).
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
// (3) Cons string. If the string is flat, replace subject with first string.
|
// (3) Cons string. If the string is flat, replace subject with first string
|
||||||
// Otherwise bailout.
|
// and go to (1). Otherwise bail out to runtime.
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
// (E) Carry on.
|
// (E) Carry on.
|
||||||
/// [...]
|
/// [...]
|
||||||
|
|
||||||
// Deferred code at the end of the stub:
|
// Deferred code at the end of the stub:
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
// Go to (5).
|
// Go to (4).
|
||||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
// (8) Sliced string. Replace subject with parent. Go to (1).
|
||||||
|
|
||||||
Label seq_string /* 5 */, external_string /* 7 */,
|
Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
|
||||||
check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
|
not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
|
||||||
not_long_external /* 8 */;
|
|
||||||
|
|
||||||
// (1) Sequential string? If yes, go to (5).
|
__ bind(&check_underlying);
|
||||||
|
__ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||||
|
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
||||||
|
|
||||||
|
// (1) Sequential string? If yes, go to (4).
|
||||||
__ And(a1,
|
__ And(a1,
|
||||||
a0,
|
a0,
|
||||||
Operand(kIsNotStringMask |
|
Operand(kIsNotStringMask |
|
||||||
@ -1719,12 +1724,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||||
__ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5).
|
__ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5).
|
||||||
|
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||||
// Go to (6).
|
// Go to (5).
|
||||||
__ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
|
__ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
|
||||||
|
|
||||||
// (3) Cons string. Check that it's flat.
|
// (3) Cons string. Check that it's flat.
|
||||||
@ -1733,19 +1738,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ LoadRoot(a1, Heap::kempty_stringRootIndex);
|
__ LoadRoot(a1, Heap::kempty_stringRootIndex);
|
||||||
__ Branch(&runtime, ne, a0, Operand(a1));
|
__ Branch(&runtime, ne, a0, Operand(a1));
|
||||||
__ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
__ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||||
|
__ jmp(&check_underlying);
|
||||||
|
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
__ bind(&check_underlying);
|
|
||||||
__ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
|
||||||
STATIC_ASSERT(kSeqStringTag == 0);
|
|
||||||
__ And(at, a0, Operand(kStringRepresentationMask));
|
|
||||||
// The underlying external string is never a short external string.
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
|
||||||
__ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7).
|
|
||||||
|
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
__ bind(&seq_string);
|
__ bind(&seq_string);
|
||||||
// subject: sequential subject string (or look-alike, external string)
|
// subject: sequential subject string (or look-alike, external string)
|
||||||
// a3: original subject string
|
// a3: original subject string
|
||||||
@ -1987,12 +1982,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||||
|
|
||||||
// Deferred code for string handling.
|
// Deferred code for string handling.
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
__ bind(¬_seq_nor_cons);
|
__ bind(¬_seq_nor_cons);
|
||||||
// Go to (8).
|
// Go to (7).
|
||||||
__ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag));
|
__ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag));
|
||||||
|
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
__ bind(&external_string);
|
__ bind(&external_string);
|
||||||
__ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
__ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
||||||
@ -2014,13 +2009,13 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
||||||
__ jmp(&seq_string); // Go to (5).
|
__ jmp(&seq_string); // Go to (5).
|
||||||
|
|
||||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||||
__ bind(¬_long_external);
|
__ bind(¬_long_external);
|
||||||
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
|
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
|
||||||
__ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
|
__ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
|
||||||
__ Branch(&runtime, ne, at, Operand(zero_reg));
|
__ Branch(&runtime, ne, at, Operand(zero_reg));
|
||||||
|
|
||||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
// (8) Sliced string. Replace subject with parent. Go to (4).
|
||||||
// Load offset into t0 and replace subject string with parent.
|
// Load offset into t0 and replace subject string with parent.
|
||||||
__ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
__ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||||
__ sra(t0, t0, kSmiTagSize);
|
__ sra(t0, t0, kSmiTagSize);
|
||||||
|
93
deps/v8/src/mips64/code-stubs-mips64.cc
vendored
93
deps/v8/src/mips64/code-stubs-mips64.cc
vendored
@ -715,13 +715,21 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
// Never falls through to here.
|
// Never falls through to here.
|
||||||
|
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
// Prepare for call to builtin. Push object pointers, a0 (lhs) first,
|
|
||||||
// a1 (rhs) second.
|
|
||||||
__ Push(lhs, rhs);
|
|
||||||
// Figure out which native to call and setup the arguments.
|
|
||||||
if (cc == eq) {
|
if (cc == eq) {
|
||||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
{
|
||||||
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ Push(lhs, rhs);
|
||||||
|
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||||
|
}
|
||||||
|
// Turn true into 0 and false into some non-zero value.
|
||||||
|
STATIC_ASSERT(EQUAL == 0);
|
||||||
|
__ LoadRoot(a0, Heap::kTrueValueRootIndex);
|
||||||
|
__ Ret(USE_DELAY_SLOT);
|
||||||
|
__ subu(v0, v0, a0); // In delay slot.
|
||||||
} else {
|
} else {
|
||||||
|
// Prepare for call to builtin. Push object pointers, a0 (lhs) first,
|
||||||
|
// a1 (rhs) second.
|
||||||
|
__ Push(lhs, rhs);
|
||||||
int ncr; // NaN compare result.
|
int ncr; // NaN compare result.
|
||||||
if (cc == lt || cc == le) {
|
if (cc == lt || cc == le) {
|
||||||
ncr = GREATER;
|
ncr = GREATER;
|
||||||
@ -1678,50 +1686,51 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ ld(subject, MemOperand(sp, kSubjectOffset));
|
__ ld(subject, MemOperand(sp, kSubjectOffset));
|
||||||
__ JumpIfSmi(subject, &runtime);
|
__ JumpIfSmi(subject, &runtime);
|
||||||
__ mov(a3, subject); // Make a copy of the original subject string.
|
__ mov(a3, subject); // Make a copy of the original subject string.
|
||||||
__ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
|
||||||
// subject: subject string
|
// subject: subject string
|
||||||
// a3: subject string
|
// a3: subject string
|
||||||
// a0: subject string instance type
|
|
||||||
// regexp_data: RegExp data (FixedArray)
|
// regexp_data: RegExp data (FixedArray)
|
||||||
// Handle subject string according to its encoding and representation:
|
// Handle subject string according to its encoding and representation:
|
||||||
// (1) Sequential string? If yes, go to (5).
|
// (1) Sequential string? If yes, go to (4).
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
// (3) Cons string. If the string is flat, replace subject with first string.
|
// (3) Cons string. If the string is flat, replace subject with first string
|
||||||
// Otherwise bailout.
|
// and go to (1). Otherwise bail out to runtime.
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
// (E) Carry on.
|
// (E) Carry on.
|
||||||
/// [...]
|
/// [...]
|
||||||
|
|
||||||
// Deferred code at the end of the stub:
|
// Deferred code at the end of the stub:
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
// Go to (5).
|
// Go to (4).
|
||||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
// (8) Sliced string. Replace subject with parent. Go to (1).
|
||||||
|
|
||||||
Label check_underlying; // (4)
|
Label check_underlying; // (1)
|
||||||
Label seq_string; // (5)
|
Label seq_string; // (4)
|
||||||
Label not_seq_nor_cons; // (6)
|
Label not_seq_nor_cons; // (5)
|
||||||
Label external_string; // (7)
|
Label external_string; // (6)
|
||||||
Label not_long_external; // (8)
|
Label not_long_external; // (7)
|
||||||
|
|
||||||
// (1) Sequential string? If yes, go to (5).
|
__ bind(&check_underlying);
|
||||||
|
__ ld(a2, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||||
|
__ lbu(a0, FieldMemOperand(a2, Map::kInstanceTypeOffset));
|
||||||
|
|
||||||
|
// (1) Sequential string? If yes, go to (4).
|
||||||
__ And(a1,
|
__ And(a1,
|
||||||
a0,
|
a0,
|
||||||
Operand(kIsNotStringMask |
|
Operand(kIsNotStringMask |
|
||||||
kStringRepresentationMask |
|
kStringRepresentationMask |
|
||||||
kShortExternalStringMask));
|
kShortExternalStringMask));
|
||||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||||
__ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5).
|
__ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (4).
|
||||||
|
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||||
// Go to (6).
|
// Go to (5).
|
||||||
__ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
|
__ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
|
||||||
|
|
||||||
// (3) Cons string. Check that it's flat.
|
// (3) Cons string. Check that it's flat.
|
||||||
@ -1730,19 +1739,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ LoadRoot(a1, Heap::kempty_stringRootIndex);
|
__ LoadRoot(a1, Heap::kempty_stringRootIndex);
|
||||||
__ Branch(&runtime, ne, a0, Operand(a1));
|
__ Branch(&runtime, ne, a0, Operand(a1));
|
||||||
__ ld(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
__ ld(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||||
|
__ jmp(&check_underlying);
|
||||||
|
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
__ bind(&check_underlying);
|
|
||||||
__ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
|
||||||
STATIC_ASSERT(kSeqStringTag == 0);
|
|
||||||
__ And(at, a0, Operand(kStringRepresentationMask));
|
|
||||||
// The underlying external string is never a short external string.
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
|
||||||
__ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7).
|
|
||||||
|
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
__ bind(&seq_string);
|
__ bind(&seq_string);
|
||||||
// subject: sequential subject string (or look-alike, external string)
|
// subject: sequential subject string (or look-alike, external string)
|
||||||
// a3: original subject string
|
// a3: original subject string
|
||||||
@ -1985,12 +1984,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||||
|
|
||||||
// Deferred code for string handling.
|
// Deferred code for string handling.
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
__ bind(¬_seq_nor_cons);
|
__ bind(¬_seq_nor_cons);
|
||||||
// Go to (8).
|
// Go to (7).
|
||||||
__ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag));
|
__ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag));
|
||||||
|
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
__ bind(&external_string);
|
__ bind(&external_string);
|
||||||
__ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
__ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
||||||
@ -2010,20 +2009,20 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ Dsubu(subject,
|
__ Dsubu(subject,
|
||||||
subject,
|
subject,
|
||||||
SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
||||||
__ jmp(&seq_string); // Go to (5).
|
__ jmp(&seq_string); // Go to (4).
|
||||||
|
|
||||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||||
__ bind(¬_long_external);
|
__ bind(¬_long_external);
|
||||||
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
|
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
|
||||||
__ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
|
__ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
|
||||||
__ Branch(&runtime, ne, at, Operand(zero_reg));
|
__ Branch(&runtime, ne, at, Operand(zero_reg));
|
||||||
|
|
||||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
// (8) Sliced string. Replace subject with parent. Go to (4).
|
||||||
// Load offset into t0 and replace subject string with parent.
|
// Load offset into t0 and replace subject string with parent.
|
||||||
__ ld(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
__ ld(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||||
__ SmiUntag(t0);
|
__ SmiUntag(t0);
|
||||||
__ ld(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
|
__ ld(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
|
||||||
__ jmp(&check_underlying); // Go to (4).
|
__ jmp(&check_underlying); // Go to (1).
|
||||||
#endif // V8_INTERPRETED_REGEXP
|
#endif // V8_INTERPRETED_REGEXP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
deps/v8/src/objects-inl.h
vendored
4
deps/v8/src/objects-inl.h
vendored
@ -1353,6 +1353,10 @@ int HeapNumber::get_sign() {
|
|||||||
|
|
||||||
|
|
||||||
bool Simd128Value::Equals(Simd128Value* that) {
|
bool Simd128Value::Equals(Simd128Value* that) {
|
||||||
|
// TODO(bmeurer): This doesn't match the SIMD.js specification, but it seems
|
||||||
|
// to be consistent with what the CompareICStub does, and what is tested in
|
||||||
|
// the current SIMD.js testsuite.
|
||||||
|
if (this == that) return true;
|
||||||
#define SIMD128_VALUE(TYPE, Type, type, lane_count, lane_type) \
|
#define SIMD128_VALUE(TYPE, Type, type, lane_count, lane_type) \
|
||||||
if (this->Is##Type()) { \
|
if (this->Is##Type()) { \
|
||||||
if (!that->Is##Type()) return false; \
|
if (!that->Is##Type()) return false; \
|
||||||
|
20
deps/v8/src/objects.cc
vendored
20
deps/v8/src/objects.cc
vendored
@ -13715,7 +13715,9 @@ void JSFunction::CalculateInstanceSizeForDerivedClass(
|
|||||||
for (PrototypeIterator iter(isolate, this,
|
for (PrototypeIterator iter(isolate, this,
|
||||||
PrototypeIterator::START_AT_RECEIVER);
|
PrototypeIterator::START_AT_RECEIVER);
|
||||||
!iter.IsAtEnd(); iter.Advance()) {
|
!iter.IsAtEnd(); iter.Advance()) {
|
||||||
JSFunction* func = iter.GetCurrent<JSFunction>();
|
JSReceiver* current = iter.GetCurrent<JSReceiver>();
|
||||||
|
if (!current->IsJSFunction()) break;
|
||||||
|
JSFunction* func = JSFunction::cast(current);
|
||||||
SharedFunctionInfo* shared = func->shared();
|
SharedFunctionInfo* shared = func->shared();
|
||||||
expected_nof_properties += shared->expected_nof_properties();
|
expected_nof_properties += shared->expected_nof_properties();
|
||||||
if (!IsSubclassConstructor(shared->kind())) {
|
if (!IsSubclassConstructor(shared->kind())) {
|
||||||
@ -17347,6 +17349,16 @@ void HashTable<Derived, Shape, Key>::Rehash(Key key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Wipe deleted entries.
|
||||||
|
Heap* heap = GetHeap();
|
||||||
|
Object* the_hole = heap->the_hole_value();
|
||||||
|
Object* undefined = heap->undefined_value();
|
||||||
|
for (uint32_t current = 0; current < capacity; current++) {
|
||||||
|
if (get(EntryToIndex(current)) == the_hole) {
|
||||||
|
set(EntryToIndex(current), undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetNumberOfDeletedElements(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -18707,6 +18719,12 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
|
|||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rehash if more than 25% of the entries are deleted entries.
|
||||||
|
// TODO(jochen): Consider to shrink the fixed array in place.
|
||||||
|
if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
|
||||||
|
table->Rehash(isolate->factory()->undefined_value());
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether the hash table should be extended.
|
// Check whether the hash table should be extended.
|
||||||
table = EnsureCapacity(table, 1, key);
|
table = EnsureCapacity(table, 1, key);
|
||||||
table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
|
table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
|
||||||
|
3
deps/v8/src/objects.h
vendored
3
deps/v8/src/objects.h
vendored
@ -9292,9 +9292,6 @@ class ExternalString: public String {
|
|||||||
static const int kResourceDataOffset = kResourceOffset + kPointerSize;
|
static const int kResourceDataOffset = kResourceOffset + kPointerSize;
|
||||||
static const int kSize = kResourceDataOffset + kPointerSize;
|
static const int kSize = kResourceDataOffset + kPointerSize;
|
||||||
|
|
||||||
static const int kMaxShortLength =
|
|
||||||
(kShortSize - SeqString::kHeaderSize) / kCharSize;
|
|
||||||
|
|
||||||
// Return whether external string is short (data pointer is not cached).
|
// Return whether external string is short (data pointer is not cached).
|
||||||
inline bool is_short();
|
inline bool is_short();
|
||||||
|
|
||||||
|
82
deps/v8/src/ppc/code-stubs-ppc.cc
vendored
82
deps/v8/src/ppc/code-stubs-ppc.cc
vendored
@ -698,11 +698,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
|
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
|
|
||||||
__ Push(lhs, rhs);
|
|
||||||
// Figure out which native to call and setup the arguments.
|
|
||||||
if (cc == eq) {
|
if (cc == eq) {
|
||||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
{
|
||||||
|
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ Push(lhs, rhs);
|
||||||
|
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||||
|
}
|
||||||
|
// Turn true into 0 and false into some non-zero value.
|
||||||
|
STATIC_ASSERT(EQUAL == 0);
|
||||||
|
__ LoadRoot(r4, Heap::kTrueValueRootIndex);
|
||||||
|
__ sub(r3, r3, r4);
|
||||||
|
__ Ret();
|
||||||
} else {
|
} else {
|
||||||
|
__ Push(lhs, rhs);
|
||||||
int ncr; // NaN compare result
|
int ncr; // NaN compare result
|
||||||
if (cc == lt || cc == le) {
|
if (cc == lt || cc == le) {
|
||||||
ncr = GREATER;
|
ncr = GREATER;
|
||||||
@ -1633,48 +1641,49 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ LoadP(subject, MemOperand(sp, kSubjectOffset));
|
__ LoadP(subject, MemOperand(sp, kSubjectOffset));
|
||||||
__ JumpIfSmi(subject, &runtime);
|
__ JumpIfSmi(subject, &runtime);
|
||||||
__ mr(r6, subject); // Make a copy of the original subject string.
|
__ mr(r6, subject); // Make a copy of the original subject string.
|
||||||
__ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
|
|
||||||
// subject: subject string
|
// subject: subject string
|
||||||
// r6: subject string
|
// r6: subject string
|
||||||
// r3: subject string instance type
|
|
||||||
// regexp_data: RegExp data (FixedArray)
|
// regexp_data: RegExp data (FixedArray)
|
||||||
// Handle subject string according to its encoding and representation:
|
// Handle subject string according to its encoding and representation:
|
||||||
// (1) Sequential string? If yes, go to (5).
|
// (1) Sequential string? If yes, go to (4).
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
// (3) Cons string. If the string is flat, replace subject with first string.
|
// (3) Cons string. If the string is flat, replace subject with first string
|
||||||
// Otherwise bailout.
|
// and go to (1). Otherwise bail out to runtime.
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
// (E) Carry on.
|
// (E) Carry on.
|
||||||
/// [...]
|
/// [...]
|
||||||
|
|
||||||
// Deferred code at the end of the stub:
|
// Deferred code at the end of the stub:
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
// Go to (5).
|
// Go to (4).
|
||||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
// (8) Sliced string. Replace subject with parent. Go to (1).
|
||||||
|
|
||||||
Label seq_string /* 5 */, external_string /* 7 */, check_underlying /* 4 */,
|
Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
|
||||||
not_seq_nor_cons /* 6 */, not_long_external /* 8 */;
|
not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
|
||||||
|
|
||||||
|
__ bind(&check_underlying);
|
||||||
|
__ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||||
|
__ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
|
||||||
|
|
||||||
|
// (1) Sequential string? If yes, go to (4).
|
||||||
|
|
||||||
// (1) Sequential string? If yes, go to (5).
|
|
||||||
STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask |
|
STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask |
|
||||||
kShortExternalStringMask) == 0x93);
|
kShortExternalStringMask) == 0x93);
|
||||||
__ andi(r4, r3, Operand(kIsNotStringMask | kStringRepresentationMask |
|
__ andi(r4, r3, Operand(kIsNotStringMask | kStringRepresentationMask |
|
||||||
kShortExternalStringMask));
|
kShortExternalStringMask));
|
||||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||||
__ beq(&seq_string, cr0); // Go to (5).
|
__ beq(&seq_string, cr0); // Go to (4).
|
||||||
|
|
||||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
// (2) Sequential or cons? If not, go to (5).
|
||||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||||
STATIC_ASSERT(kExternalStringTag < 0xffffu);
|
STATIC_ASSERT(kExternalStringTag < 0xffffu);
|
||||||
__ cmpi(r4, Operand(kExternalStringTag));
|
__ cmpi(r4, Operand(kExternalStringTag));
|
||||||
__ bge(¬_seq_nor_cons); // Go to (6).
|
__ bge(¬_seq_nor_cons); // Go to (5).
|
||||||
|
|
||||||
// (3) Cons string. Check that it's flat.
|
// (3) Cons string. Check that it's flat.
|
||||||
// Replace subject with first string and reload instance type.
|
// Replace subject with first string and reload instance type.
|
||||||
@ -1682,20 +1691,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ CompareRoot(r3, Heap::kempty_stringRootIndex);
|
__ CompareRoot(r3, Heap::kempty_stringRootIndex);
|
||||||
__ bne(&runtime);
|
__ bne(&runtime);
|
||||||
__ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
__ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||||
|
__ b(&check_underlying);
|
||||||
|
|
||||||
// (4) Is subject external? If yes, go to (7).
|
// (4) Sequential string. Load regexp code according to encoding.
|
||||||
__ bind(&check_underlying);
|
|
||||||
__ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
|
|
||||||
__ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
|
|
||||||
STATIC_ASSERT(kSeqStringTag == 0);
|
|
||||||
STATIC_ASSERT(kStringRepresentationMask == 3);
|
|
||||||
__ andi(r0, r3, Operand(kStringRepresentationMask));
|
|
||||||
// The underlying external string is never a short external string.
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
|
||||||
__ bne(&external_string, cr0); // Go to (7).
|
|
||||||
|
|
||||||
// (5) Sequential string. Load regexp code according to encoding.
|
|
||||||
__ bind(&seq_string);
|
__ bind(&seq_string);
|
||||||
// subject: sequential subject string (or look-alike, external string)
|
// subject: sequential subject string (or look-alike, external string)
|
||||||
// r6: original subject string
|
// r6: original subject string
|
||||||
@ -1928,12 +1926,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||||
|
|
||||||
// Deferred code for string handling.
|
// Deferred code for string handling.
|
||||||
// (6) Not a long external string? If yes, go to (8).
|
// (5) Long external string? If not, go to (7).
|
||||||
__ bind(¬_seq_nor_cons);
|
__ bind(¬_seq_nor_cons);
|
||||||
// Compare flags are still set.
|
// Compare flags are still set.
|
||||||
__ bgt(¬_long_external); // Go to (8).
|
__ bgt(¬_long_external); // Go to (7).
|
||||||
|
|
||||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||||
__ bind(&external_string);
|
__ bind(&external_string);
|
||||||
__ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
|
__ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||||
__ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
|
__ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
|
||||||
@ -1950,15 +1948,15 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||||
__ subi(subject, subject,
|
__ subi(subject, subject,
|
||||||
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||||
__ b(&seq_string); // Go to (5).
|
__ b(&seq_string); // Go to (4).
|
||||||
|
|
||||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||||
__ bind(¬_long_external);
|
__ bind(¬_long_external);
|
||||||
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0);
|
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0);
|
||||||
__ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask));
|
__ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask));
|
||||||
__ bne(&runtime, cr0);
|
__ bne(&runtime, cr0);
|
||||||
|
|
||||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
// (8) Sliced string. Replace subject with parent. Go to (4).
|
||||||
// Load offset into r11 and replace subject string with parent.
|
// Load offset into r11 and replace subject string with parent.
|
||||||
__ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
__ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||||
__ SmiUntag(r11);
|
__ SmiUntag(r11);
|
||||||
|
103
deps/v8/src/runtime/runtime-interpreter.cc
vendored
103
deps/v8/src/runtime/runtime-interpreter.cc
vendored
@ -16,109 +16,6 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_InterpreterEquals) {
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
|
||||||
Maybe<bool> result = Object::Equals(x, y);
|
|
||||||
if (result.IsJust()) {
|
|
||||||
return isolate->heap()->ToBoolean(result.FromJust());
|
|
||||||
} else {
|
|
||||||
return isolate->heap()->exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_InterpreterNotEquals) {
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
|
||||||
Maybe<bool> result = Object::Equals(x, y);
|
|
||||||
if (result.IsJust()) {
|
|
||||||
return isolate->heap()->ToBoolean(!result.FromJust());
|
|
||||||
} else {
|
|
||||||
return isolate->heap()->exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_InterpreterLessThan) {
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
|
||||||
Maybe<bool> result = Object::LessThan(x, y);
|
|
||||||
if (result.IsJust()) {
|
|
||||||
return isolate->heap()->ToBoolean(result.FromJust());
|
|
||||||
} else {
|
|
||||||
return isolate->heap()->exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_InterpreterGreaterThan) {
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
|
||||||
Maybe<bool> result = Object::GreaterThan(x, y);
|
|
||||||
if (result.IsJust()) {
|
|
||||||
return isolate->heap()->ToBoolean(result.FromJust());
|
|
||||||
} else {
|
|
||||||
return isolate->heap()->exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_InterpreterLessThanOrEqual) {
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
|
||||||
Maybe<bool> result = Object::LessThanOrEqual(x, y);
|
|
||||||
if (result.IsJust()) {
|
|
||||||
return isolate->heap()->ToBoolean(result.FromJust());
|
|
||||||
} else {
|
|
||||||
return isolate->heap()->exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_InterpreterGreaterThanOrEqual) {
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
|
||||||
Maybe<bool> result = Object::GreaterThanOrEqual(x, y);
|
|
||||||
if (result.IsJust()) {
|
|
||||||
return isolate->heap()->ToBoolean(result.FromJust());
|
|
||||||
} else {
|
|
||||||
return isolate->heap()->exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_InterpreterStrictEquals) {
|
|
||||||
SealHandleScope shs(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_CHECKED(Object, y, 1);
|
|
||||||
return isolate->heap()->ToBoolean(x->StrictEquals(y));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_InterpreterStrictNotEquals) {
|
|
||||||
SealHandleScope shs(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_CHECKED(Object, y, 1);
|
|
||||||
return isolate->heap()->ToBoolean(!x->StrictEquals(y));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_InterpreterToBoolean) {
|
RUNTIME_FUNCTION(Runtime_InterpreterToBoolean) {
|
||||||
SealHandleScope shs(isolate);
|
SealHandleScope shs(isolate);
|
||||||
DCHECK_EQ(1, args.length());
|
DCHECK_EQ(1, args.length());
|
||||||
|
22
deps/v8/src/runtime/runtime-object.cc
vendored
22
deps/v8/src/runtime/runtime-object.cc
vendored
@ -1073,28 +1073,6 @@ RUNTIME_FUNCTION(Runtime_ToName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_Equals) {
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
|
||||||
Maybe<bool> result = Object::Equals(x, y);
|
|
||||||
if (!result.IsJust()) return isolate->heap()->exception();
|
|
||||||
// TODO(bmeurer): Change this at some point to return true/false instead.
|
|
||||||
return Smi::FromInt(result.FromJust() ? EQUAL : NOT_EQUAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_StrictEquals) {
|
|
||||||
SealHandleScope scope(isolate);
|
|
||||||
DCHECK_EQ(2, args.length());
|
|
||||||
CONVERT_ARG_CHECKED(Object, x, 0);
|
|
||||||
CONVERT_ARG_CHECKED(Object, y, 1);
|
|
||||||
// TODO(bmeurer): Change this at some point to return true/false instead.
|
|
||||||
return Smi::FromInt(x->StrictEquals(y) ? EQUAL : NOT_EQUAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_SameValue) {
|
RUNTIME_FUNCTION(Runtime_SameValue) {
|
||||||
SealHandleScope scope(isolate);
|
SealHandleScope scope(isolate);
|
||||||
DCHECK_EQ(2, args.length());
|
DCHECK_EQ(2, args.length());
|
||||||
|
76
deps/v8/src/runtime/runtime-operators.cc
vendored
76
deps/v8/src/runtime/runtime-operators.cc
vendored
@ -140,5 +140,81 @@ RUNTIME_FUNCTION(Runtime_BitwiseXor) {
|
|||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(Runtime_Equal) {
|
||||||
|
HandleScope scope(isolate);
|
||||||
|
DCHECK_EQ(2, args.length());
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
||||||
|
Maybe<bool> result = Object::Equals(x, y);
|
||||||
|
if (!result.IsJust()) return isolate->heap()->exception();
|
||||||
|
return isolate->heap()->ToBoolean(result.FromJust());
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(Runtime_NotEqual) {
|
||||||
|
HandleScope scope(isolate);
|
||||||
|
DCHECK_EQ(2, args.length());
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
||||||
|
Maybe<bool> result = Object::Equals(x, y);
|
||||||
|
if (!result.IsJust()) return isolate->heap()->exception();
|
||||||
|
return isolate->heap()->ToBoolean(!result.FromJust());
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(Runtime_StrictEqual) {
|
||||||
|
SealHandleScope scope(isolate);
|
||||||
|
DCHECK_EQ(2, args.length());
|
||||||
|
CONVERT_ARG_CHECKED(Object, x, 0);
|
||||||
|
CONVERT_ARG_CHECKED(Object, y, 1);
|
||||||
|
return isolate->heap()->ToBoolean(x->StrictEquals(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(Runtime_StrictNotEqual) {
|
||||||
|
SealHandleScope scope(isolate);
|
||||||
|
DCHECK_EQ(2, args.length());
|
||||||
|
CONVERT_ARG_CHECKED(Object, x, 0);
|
||||||
|
CONVERT_ARG_CHECKED(Object, y, 1);
|
||||||
|
return isolate->heap()->ToBoolean(!x->StrictEquals(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(Runtime_LessThan) {
|
||||||
|
HandleScope scope(isolate);
|
||||||
|
DCHECK_EQ(2, args.length());
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
||||||
|
Maybe<bool> result = Object::LessThan(x, y);
|
||||||
|
if (!result.IsJust()) return isolate->heap()->exception();
|
||||||
|
return isolate->heap()->ToBoolean(result.FromJust());
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(Runtime_GreaterThan) {
|
||||||
|
HandleScope scope(isolate);
|
||||||
|
DCHECK_EQ(2, args.length());
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
||||||
|
Maybe<bool> result = Object::GreaterThan(x, y);
|
||||||
|
if (!result.IsJust()) return isolate->heap()->exception();
|
||||||
|
return isolate->heap()->ToBoolean(result.FromJust());
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(Runtime_LessThanOrEqual) {
|
||||||
|
HandleScope scope(isolate);
|
||||||
|
DCHECK_EQ(2, args.length());
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
||||||
|
Maybe<bool> result = Object::LessThanOrEqual(x, y);
|
||||||
|
if (!result.IsJust()) return isolate->heap()->exception();
|
||||||
|
return isolate->heap()->ToBoolean(result.FromJust());
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(Runtime_GreaterThanOrEqual) {
|
||||||
|
HandleScope scope(isolate);
|
||||||
|
DCHECK_EQ(2, args.length());
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
||||||
|
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
||||||
|
Maybe<bool> result = Object::GreaterThanOrEqual(x, y);
|
||||||
|
if (!result.IsJust()) return isolate->heap()->exception();
|
||||||
|
return isolate->heap()->ToBoolean(result.FromJust());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
20
deps/v8/src/runtime/runtime.h
vendored
20
deps/v8/src/runtime/runtime.h
vendored
@ -206,14 +206,6 @@ namespace internal {
|
|||||||
F(ForInStep, 1, 1)
|
F(ForInStep, 1, 1)
|
||||||
|
|
||||||
#define FOR_EACH_INTRINSIC_INTERPRETER(F) \
|
#define FOR_EACH_INTRINSIC_INTERPRETER(F) \
|
||||||
F(InterpreterEquals, 2, 1) \
|
|
||||||
F(InterpreterNotEquals, 2, 1) \
|
|
||||||
F(InterpreterStrictEquals, 2, 1) \
|
|
||||||
F(InterpreterStrictNotEquals, 2, 1) \
|
|
||||||
F(InterpreterLessThan, 2, 1) \
|
|
||||||
F(InterpreterGreaterThan, 2, 1) \
|
|
||||||
F(InterpreterLessThanOrEqual, 2, 1) \
|
|
||||||
F(InterpreterGreaterThanOrEqual, 2, 1) \
|
|
||||||
F(InterpreterToBoolean, 1, 1) \
|
F(InterpreterToBoolean, 1, 1) \
|
||||||
F(InterpreterLogicalNot, 1, 1) \
|
F(InterpreterLogicalNot, 1, 1) \
|
||||||
F(InterpreterTypeOf, 1, 1) \
|
F(InterpreterTypeOf, 1, 1) \
|
||||||
@ -461,8 +453,6 @@ namespace internal {
|
|||||||
F(ToLength, 1, 1) \
|
F(ToLength, 1, 1) \
|
||||||
F(ToString, 1, 1) \
|
F(ToString, 1, 1) \
|
||||||
F(ToName, 1, 1) \
|
F(ToName, 1, 1) \
|
||||||
F(Equals, 2, 1) \
|
|
||||||
F(StrictEquals, 2, 1) \
|
|
||||||
F(SameValue, 2, 1) \
|
F(SameValue, 2, 1) \
|
||||||
F(SameValueZero, 2, 1) \
|
F(SameValueZero, 2, 1) \
|
||||||
F(Compare, 3, 1) \
|
F(Compare, 3, 1) \
|
||||||
@ -497,7 +487,15 @@ namespace internal {
|
|||||||
F(ShiftRightLogical, 2, 1) \
|
F(ShiftRightLogical, 2, 1) \
|
||||||
F(BitwiseAnd, 2, 1) \
|
F(BitwiseAnd, 2, 1) \
|
||||||
F(BitwiseOr, 2, 1) \
|
F(BitwiseOr, 2, 1) \
|
||||||
F(BitwiseXor, 2, 1)
|
F(BitwiseXor, 2, 1) \
|
||||||
|
F(Equal, 2, 1) \
|
||||||
|
F(NotEqual, 2, 1) \
|
||||||
|
F(StrictEqual, 2, 1) \
|
||||||
|
F(StrictNotEqual, 2, 1) \
|
||||||
|
F(LessThan, 2, 1) \
|
||||||
|
F(GreaterThan, 2, 1) \
|
||||||
|
F(LessThanOrEqual, 2, 1) \
|
||||||
|
F(GreaterThanOrEqual, 2, 1)
|
||||||
|
|
||||||
#define FOR_EACH_INTRINSIC_PROXY(F) \
|
#define FOR_EACH_INTRINSIC_PROXY(F) \
|
||||||
F(IsJSProxy, 1, 1) \
|
F(IsJSProxy, 1, 1) \
|
||||||
|
33
deps/v8/src/type-feedback-vector.cc
vendored
33
deps/v8/src/type-feedback-vector.cc
vendored
@ -340,6 +340,10 @@ void FeedbackNexus::ConfigurePremonomorphic() {
|
|||||||
|
|
||||||
|
|
||||||
void FeedbackNexus::ConfigureMegamorphic() {
|
void FeedbackNexus::ConfigureMegamorphic() {
|
||||||
|
// Keyed ICs must use ConfigureMegamorphicKeyed.
|
||||||
|
DCHECK_NE(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector()->GetKind(slot()));
|
||||||
|
DCHECK_NE(FeedbackVectorSlotKind::KEYED_STORE_IC, vector()->GetKind(slot()));
|
||||||
|
|
||||||
Isolate* isolate = GetIsolate();
|
Isolate* isolate = GetIsolate();
|
||||||
SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
|
SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
|
||||||
SKIP_WRITE_BARRIER);
|
SKIP_WRITE_BARRIER);
|
||||||
@ -347,6 +351,21 @@ void FeedbackNexus::ConfigureMegamorphic() {
|
|||||||
SKIP_WRITE_BARRIER);
|
SKIP_WRITE_BARRIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyedLoadICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) {
|
||||||
|
Isolate* isolate = GetIsolate();
|
||||||
|
SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
|
||||||
|
SKIP_WRITE_BARRIER);
|
||||||
|
SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
|
||||||
|
SKIP_WRITE_BARRIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyedStoreICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) {
|
||||||
|
Isolate* isolate = GetIsolate();
|
||||||
|
SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
|
||||||
|
SKIP_WRITE_BARRIER);
|
||||||
|
SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
|
||||||
|
SKIP_WRITE_BARRIER);
|
||||||
|
}
|
||||||
|
|
||||||
InlineCacheState LoadICNexus::StateFromFeedback() const {
|
InlineCacheState LoadICNexus::StateFromFeedback() const {
|
||||||
Isolate* isolate = GetIsolate();
|
Isolate* isolate = GetIsolate();
|
||||||
@ -824,10 +843,20 @@ KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
|
|||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IcCheckType KeyedLoadICNexus::GetKeyType() const {
|
||||||
|
Object* feedback = GetFeedback();
|
||||||
|
if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) {
|
||||||
|
return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value());
|
||||||
|
}
|
||||||
|
return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
IcCheckType KeyedStoreICNexus::GetKeyType() const {
|
IcCheckType KeyedStoreICNexus::GetKeyType() const {
|
||||||
// The structure of the vector slots tells us the type.
|
Object* feedback = GetFeedback();
|
||||||
return GetFeedback()->IsName() ? PROPERTY : ELEMENT;
|
if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) {
|
||||||
|
return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value());
|
||||||
|
}
|
||||||
|
return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
|
||||||
}
|
}
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
4
deps/v8/src/type-feedback-vector.h
vendored
4
deps/v8/src/type-feedback-vector.h
vendored
@ -475,6 +475,9 @@ class KeyedLoadICNexus : public FeedbackNexus {
|
|||||||
void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
|
void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
|
||||||
CodeHandleList* handlers);
|
CodeHandleList* handlers);
|
||||||
|
|
||||||
|
void ConfigureMegamorphicKeyed(IcCheckType property_type);
|
||||||
|
|
||||||
|
IcCheckType GetKeyType() const;
|
||||||
InlineCacheState StateFromFeedback() const override;
|
InlineCacheState StateFromFeedback() const override;
|
||||||
Name* FindFirstName() const override;
|
Name* FindFirstName() const override;
|
||||||
};
|
};
|
||||||
@ -531,6 +534,7 @@ class KeyedStoreICNexus : public FeedbackNexus {
|
|||||||
void ConfigurePolymorphic(MapHandleList* maps,
|
void ConfigurePolymorphic(MapHandleList* maps,
|
||||||
MapHandleList* transitioned_maps,
|
MapHandleList* transitioned_maps,
|
||||||
CodeHandleList* handlers);
|
CodeHandleList* handlers);
|
||||||
|
void ConfigureMegamorphicKeyed(IcCheckType property_type);
|
||||||
|
|
||||||
KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
|
KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
|
||||||
IcCheckType GetKeyType() const;
|
IcCheckType GetKeyType() const;
|
||||||
|
2
deps/v8/src/type-info.cc
vendored
2
deps/v8/src/type-info.cc
vendored
@ -301,7 +301,7 @@ void TypeFeedbackOracle::KeyedPropertyReceiverTypes(
|
|||||||
KeyedLoadICNexus nexus(feedback_vector_, slot);
|
KeyedLoadICNexus nexus(feedback_vector_, slot);
|
||||||
CollectReceiverTypes<FeedbackNexus>(&nexus, receiver_types);
|
CollectReceiverTypes<FeedbackNexus>(&nexus, receiver_types);
|
||||||
*is_string = HasOnlyStringMaps(receiver_types);
|
*is_string = HasOnlyStringMaps(receiver_types);
|
||||||
*key_type = nexus.FindFirstName() != NULL ? PROPERTY : ELEMENT;
|
*key_type = nexus.GetKeyType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
95
deps/v8/src/x64/code-stubs-x64.cc
vendored
95
deps/v8/src/x64/code-stubs-x64.cc
vendored
@ -667,35 +667,34 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
|
__ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
|
||||||
__ JumpIfSmi(rdi, &runtime);
|
__ JumpIfSmi(rdi, &runtime);
|
||||||
__ movp(r15, rdi); // Make a copy of the original subject string.
|
__ movp(r15, rdi); // Make a copy of the original subject string.
|
||||||
__ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
|
|
||||||
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
|
|
||||||
// rax: RegExp data (FixedArray)
|
// rax: RegExp data (FixedArray)
|
||||||
// rdi: subject string
|
// rdi: subject string
|
||||||
// r15: subject string
|
// r15: subject string
|
||||||
// Handle subject string according to its encoding and representation:
|
// Handle subject string according to its encoding and representation:
|
||||||
// (1) Sequential two byte? If yes, go to (9).
|
// (1) Sequential two byte? If yes, go to (9).
|
||||||
// (2) Sequential one byte? If yes, go to (6).
|
// (2) Sequential one byte? If yes, go to (5).
|
||||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
// (3) Sequential or cons? If not, go to (6).
|
||||||
// (4) Cons string. If the string is flat, replace subject with first string.
|
// (4) Cons string. If the string is flat, replace subject with first string
|
||||||
// Otherwise bailout.
|
// and go to (1). Otherwise bail out to runtime.
|
||||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
// (5) One byte sequential. Load regexp code for one byte.
|
||||||
// (5b) Is subject external? If yes, go to (8).
|
|
||||||
// (6) One byte sequential. Load regexp code for one byte.
|
|
||||||
// (E) Carry on.
|
// (E) Carry on.
|
||||||
/// [...]
|
/// [...]
|
||||||
|
|
||||||
// Deferred code at the end of the stub:
|
// Deferred code at the end of the stub:
|
||||||
// (7) Not a long external string? If yes, go to (10).
|
// (6) Long external string? If not, go to (10).
|
||||||
// (8) External string. Make it, offset-wise, look like a sequential string.
|
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||||
// (8a) Is the external string one byte? If yes, go to (6).
|
// (8) Is the external string one byte? If yes, go to (5).
|
||||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||||
// (10) Short external string or not a string? If yes, bail out to runtime.
|
// (10) Short external string or not a string? If yes, bail out to runtime.
|
||||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||||
|
|
||||||
Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
|
Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
|
||||||
external_string /* 8 */, check_underlying /* 5a */,
|
external_string /* 7 */, check_underlying /* 1 */,
|
||||||
not_seq_nor_cons /* 7 */, check_code /* E */,
|
not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
|
||||||
not_long_external /* 10 */;
|
|
||||||
|
__ bind(&check_underlying);
|
||||||
|
__ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
|
||||||
|
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
|
||||||
|
|
||||||
// (1) Sequential two byte? If yes, go to (9).
|
// (1) Sequential two byte? If yes, go to (9).
|
||||||
__ andb(rbx, Immediate(kIsNotStringMask |
|
__ andb(rbx, Immediate(kIsNotStringMask |
|
||||||
@ -705,14 +704,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
||||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
__ j(zero, &seq_two_byte_string); // Go to (9).
|
||||||
|
|
||||||
// (2) Sequential one byte? If yes, go to (6).
|
// (2) Sequential one byte? If yes, go to (5).
|
||||||
// Any other sequential string must be one byte.
|
// Any other sequential string must be one byte.
|
||||||
__ andb(rbx, Immediate(kIsNotStringMask |
|
__ andb(rbx, Immediate(kIsNotStringMask |
|
||||||
kStringRepresentationMask |
|
kStringRepresentationMask |
|
||||||
kShortExternalStringMask));
|
kShortExternalStringMask));
|
||||||
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6).
|
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
|
||||||
|
|
||||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
// (3) Sequential or cons? If not, go to (6).
|
||||||
// We check whether the subject string is a cons, since sequential strings
|
// We check whether the subject string is a cons, since sequential strings
|
||||||
// have already been covered.
|
// have already been covered.
|
||||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||||
@ -720,7 +719,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||||
__ cmpp(rbx, Immediate(kExternalStringTag));
|
__ cmpp(rbx, Immediate(kExternalStringTag));
|
||||||
__ j(greater_equal, ¬_seq_nor_cons); // Go to (7).
|
__ j(greater_equal, ¬_seq_nor_cons); // Go to (6).
|
||||||
|
|
||||||
// (4) Cons string. Check that it's flat.
|
// (4) Cons string. Check that it's flat.
|
||||||
// Replace subject with first string and reload instance type.
|
// Replace subject with first string and reload instance type.
|
||||||
@ -728,22 +727,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
Heap::kempty_stringRootIndex);
|
Heap::kempty_stringRootIndex);
|
||||||
__ j(not_equal, &runtime);
|
__ j(not_equal, &runtime);
|
||||||
__ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
|
__ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
|
||||||
__ bind(&check_underlying);
|
__ jmp(&check_underlying);
|
||||||
__ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
|
|
||||||
__ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
|
|
||||||
|
|
||||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
// (5) One byte sequential. Load regexp code for one byte.
|
||||||
__ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask));
|
|
||||||
STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
|
|
||||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
|
||||||
// (5b) Is subject external? If yes, go to (8).
|
|
||||||
__ testb(rbx, Immediate(kStringRepresentationMask));
|
|
||||||
// The underlying external string is never a short external string.
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
|
||||||
__ j(not_zero, &external_string); // Go to (8)
|
|
||||||
|
|
||||||
// (6) One byte sequential. Load regexp code for one byte.
|
|
||||||
__ bind(&seq_one_byte_string);
|
__ bind(&seq_one_byte_string);
|
||||||
// rax: RegExp data (FixedArray)
|
// rax: RegExp data (FixedArray)
|
||||||
__ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset));
|
__ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset));
|
||||||
@ -990,12 +976,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||||
|
|
||||||
// Deferred code for string handling.
|
// Deferred code for string handling.
|
||||||
// (7) Not a long external string? If yes, go to (10).
|
// (6) Long external string? If not, go to (10).
|
||||||
__ bind(¬_seq_nor_cons);
|
__ bind(¬_seq_nor_cons);
|
||||||
// Compare flags are still set from (3).
|
// Compare flags are still set from (3).
|
||||||
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
|
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
|
||||||
|
|
||||||
// (8) External string. Short external strings have been ruled out.
|
// (7) External string. Short external strings have been ruled out.
|
||||||
__ bind(&external_string);
|
__ bind(&external_string);
|
||||||
__ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
|
__ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
|
||||||
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
|
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
|
||||||
@ -1010,13 +996,13 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||||
__ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
__ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||||
// (8a) Is the external string one byte? If yes, go to (6).
|
// (8) Is the external string one byte? If yes, go to (5).
|
||||||
__ testb(rbx, Immediate(kStringEncodingMask));
|
__ testb(rbx, Immediate(kStringEncodingMask));
|
||||||
__ j(not_zero, &seq_one_byte_string); // Goto (6).
|
__ j(not_zero, &seq_one_byte_string); // Go to (5).
|
||||||
|
|
||||||
// rdi: subject string (flat two-byte)
|
// rdi: subject string (flat two-byte)
|
||||||
// rax: RegExp data (FixedArray)
|
// rax: RegExp data (FixedArray)
|
||||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||||
__ bind(&seq_two_byte_string);
|
__ bind(&seq_two_byte_string);
|
||||||
__ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
|
__ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
|
||||||
__ Set(rcx, 0); // Type is two byte.
|
__ Set(rcx, 0); // Type is two byte.
|
||||||
@ -1029,7 +1015,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask));
|
__ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask));
|
||||||
__ j(not_zero, &runtime);
|
__ j(not_zero, &runtime);
|
||||||
|
|
||||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||||
// Load offset into r14 and replace subject string with parent.
|
// Load offset into r14 and replace subject string with parent.
|
||||||
__ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset));
|
__ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset));
|
||||||
__ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
|
__ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
|
||||||
@ -1320,16 +1306,23 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
__ bind(&runtime_call);
|
__ bind(&runtime_call);
|
||||||
|
|
||||||
// Push arguments below the return address to prepare jump to builtin.
|
|
||||||
__ PopReturnAddressTo(rcx);
|
|
||||||
__ Push(rdx);
|
|
||||||
__ Push(rax);
|
|
||||||
|
|
||||||
// Figure out which native to call and setup the arguments.
|
|
||||||
if (cc == equal) {
|
if (cc == equal) {
|
||||||
__ PushReturnAddressFrom(rcx);
|
{
|
||||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ Push(rdx);
|
||||||
|
__ Push(rax);
|
||||||
|
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||||
|
}
|
||||||
|
// Turn true into 0 and false into some non-zero value.
|
||||||
|
STATIC_ASSERT(EQUAL == 0);
|
||||||
|
__ LoadRoot(rdx, Heap::kTrueValueRootIndex);
|
||||||
|
__ subp(rax, rdx);
|
||||||
|
__ Ret();
|
||||||
} else {
|
} else {
|
||||||
|
// Push arguments below the return address to prepare jump to builtin.
|
||||||
|
__ PopReturnAddressTo(rcx);
|
||||||
|
__ Push(rdx);
|
||||||
|
__ Push(rax);
|
||||||
__ Push(Smi::FromInt(NegativeComparisonResult(cc)));
|
__ Push(Smi::FromInt(NegativeComparisonResult(cc)));
|
||||||
__ PushReturnAddressFrom(rcx);
|
__ PushReturnAddressFrom(rcx);
|
||||||
__ TailCallRuntime(Runtime::kCompare);
|
__ TailCallRuntime(Runtime::kCompare);
|
||||||
|
98
deps/v8/src/x87/code-stubs-x87.cc
vendored
98
deps/v8/src/x87/code-stubs-x87.cc
vendored
@ -500,39 +500,37 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ mov(eax, Operand(esp, kSubjectOffset));
|
__ mov(eax, Operand(esp, kSubjectOffset));
|
||||||
__ JumpIfSmi(eax, &runtime);
|
__ JumpIfSmi(eax, &runtime);
|
||||||
__ mov(edx, eax); // Make a copy of the original subject string.
|
__ mov(edx, eax); // Make a copy of the original subject string.
|
||||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
|
||||||
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
|
||||||
|
|
||||||
// eax: subject string
|
// eax: subject string
|
||||||
// edx: subject string
|
// edx: subject string
|
||||||
// ebx: subject string instance type
|
|
||||||
// ecx: RegExp data (FixedArray)
|
// ecx: RegExp data (FixedArray)
|
||||||
// Handle subject string according to its encoding and representation:
|
// Handle subject string according to its encoding and representation:
|
||||||
// (1) Sequential two byte? If yes, go to (9).
|
// (1) Sequential two byte? If yes, go to (9).
|
||||||
// (2) Sequential one byte? If yes, go to (6).
|
// (2) Sequential one byte? If yes, go to (5).
|
||||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
// (3) Sequential or cons? If not, go to (6).
|
||||||
// (4) Cons string. If the string is flat, replace subject with first string.
|
// (4) Cons string. If the string is flat, replace subject with first string
|
||||||
// Otherwise bailout.
|
// and go to (1). Otherwise bail out to runtime.
|
||||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
// (5) One byte sequential. Load regexp code for one byte.
|
||||||
// (5b) Is subject external? If yes, go to (8).
|
|
||||||
// (6) One byte sequential. Load regexp code for one byte.
|
|
||||||
// (E) Carry on.
|
// (E) Carry on.
|
||||||
/// [...]
|
/// [...]
|
||||||
|
|
||||||
// Deferred code at the end of the stub:
|
// Deferred code at the end of the stub:
|
||||||
// (7) Not a long external string? If yes, go to (10).
|
// (6) Long external string? If not, go to (10).
|
||||||
// (8) External string. Make it, offset-wise, look like a sequential string.
|
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||||
// (8a) Is the external string one byte? If yes, go to (6).
|
// (8) Is the external string one byte? If yes, go to (5).
|
||||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||||
// (10) Short external string or not a string? If yes, bail out to runtime.
|
// (10) Short external string or not a string? If yes, bail out to runtime.
|
||||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||||
|
|
||||||
Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
|
Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
|
||||||
external_string /* 8 */, check_underlying /* 5a */,
|
external_string /* 7 */, check_underlying /* 1 */,
|
||||||
not_seq_nor_cons /* 7 */, check_code /* E */,
|
not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
|
||||||
not_long_external /* 10 */;
|
|
||||||
|
|
||||||
|
__ bind(&check_underlying);
|
||||||
// (1) Sequential two byte? If yes, go to (9).
|
// (1) Sequential two byte? If yes, go to (9).
|
||||||
|
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||||
|
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
||||||
|
|
||||||
__ and_(ebx, kIsNotStringMask |
|
__ and_(ebx, kIsNotStringMask |
|
||||||
kStringRepresentationMask |
|
kStringRepresentationMask |
|
||||||
kStringEncodingMask |
|
kStringEncodingMask |
|
||||||
@ -540,14 +538,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
||||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
__ j(zero, &seq_two_byte_string); // Go to (9).
|
||||||
|
|
||||||
// (2) Sequential one byte? If yes, go to (6).
|
// (2) Sequential one byte? If yes, go to (5).
|
||||||
// Any other sequential string must be one byte.
|
// Any other sequential string must be one byte.
|
||||||
__ and_(ebx, Immediate(kIsNotStringMask |
|
__ and_(ebx, Immediate(kIsNotStringMask |
|
||||||
kStringRepresentationMask |
|
kStringRepresentationMask |
|
||||||
kShortExternalStringMask));
|
kShortExternalStringMask));
|
||||||
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6).
|
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
|
||||||
|
|
||||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
// (3) Sequential or cons? If not, go to (6).
|
||||||
// We check whether the subject string is a cons, since sequential strings
|
// We check whether the subject string is a cons, since sequential strings
|
||||||
// have already been covered.
|
// have already been covered.
|
||||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||||
@ -555,32 +553,19 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||||
__ cmp(ebx, Immediate(kExternalStringTag));
|
__ cmp(ebx, Immediate(kExternalStringTag));
|
||||||
__ j(greater_equal, ¬_seq_nor_cons); // Go to (7).
|
__ j(greater_equal, ¬_seq_nor_cons); // Go to (6).
|
||||||
|
|
||||||
// (4) Cons string. Check that it's flat.
|
// (4) Cons string. Check that it's flat.
|
||||||
// Replace subject with first string and reload instance type.
|
// Replace subject with first string and reload instance type.
|
||||||
__ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
|
__ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
|
||||||
__ j(not_equal, &runtime);
|
__ j(not_equal, &runtime);
|
||||||
__ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
|
__ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
|
||||||
__ bind(&check_underlying);
|
__ jmp(&check_underlying);
|
||||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
|
||||||
__ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
|
||||||
|
|
||||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
|
||||||
__ test_b(ebx, kStringRepresentationMask | kStringEncodingMask);
|
|
||||||
STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
|
|
||||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
|
||||||
// (5b) Is subject external? If yes, go to (8).
|
|
||||||
__ test_b(ebx, kStringRepresentationMask);
|
|
||||||
// The underlying external string is never a short external string.
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
|
||||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
|
||||||
__ j(not_zero, &external_string); // Go to (8).
|
|
||||||
|
|
||||||
// eax: sequential subject string (or look-alike, external string)
|
// eax: sequential subject string (or look-alike, external string)
|
||||||
// edx: original subject string
|
// edx: original subject string
|
||||||
// ecx: RegExp data (FixedArray)
|
// ecx: RegExp data (FixedArray)
|
||||||
// (6) One byte sequential. Load regexp code for one byte.
|
// (5) One byte sequential. Load regexp code for one byte.
|
||||||
__ bind(&seq_one_byte_string);
|
__ bind(&seq_one_byte_string);
|
||||||
// Load previous index and check range before edx is overwritten. We have
|
// Load previous index and check range before edx is overwritten. We have
|
||||||
// to use edx instead of eax here because it might have been only made to
|
// to use edx instead of eax here because it might have been only made to
|
||||||
@ -801,12 +786,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||||
|
|
||||||
// Deferred code for string handling.
|
// Deferred code for string handling.
|
||||||
// (7) Not a long external string? If yes, go to (10).
|
// (6) Long external string? If not, go to (10).
|
||||||
__ bind(¬_seq_nor_cons);
|
__ bind(¬_seq_nor_cons);
|
||||||
// Compare flags are still set from (3).
|
// Compare flags are still set from (3).
|
||||||
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
|
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
|
||||||
|
|
||||||
// (8) External string. Short external strings have been ruled out.
|
// (7) External string. Short external strings have been ruled out.
|
||||||
__ bind(&external_string);
|
__ bind(&external_string);
|
||||||
// Reload instance type.
|
// Reload instance type.
|
||||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||||
@ -822,14 +807,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||||
__ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
__ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||||
// (8a) Is the external string one byte? If yes, go to (6).
|
// (8) Is the external string one byte? If yes, go to (5).
|
||||||
__ test_b(ebx, kStringEncodingMask);
|
__ test_b(ebx, kStringEncodingMask);
|
||||||
__ j(not_zero, &seq_one_byte_string); // Goto (6).
|
__ j(not_zero, &seq_one_byte_string); // Go to (5).
|
||||||
|
|
||||||
// eax: sequential subject string (or look-alike, external string)
|
// eax: sequential subject string (or look-alike, external string)
|
||||||
// edx: original subject string
|
// edx: original subject string
|
||||||
// ecx: RegExp data (FixedArray)
|
// ecx: RegExp data (FixedArray)
|
||||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||||
__ bind(&seq_two_byte_string);
|
__ bind(&seq_two_byte_string);
|
||||||
// Load previous index and check range before edx is overwritten. We have
|
// Load previous index and check range before edx is overwritten. We have
|
||||||
// to use edx instead of eax here because it might have been only made to
|
// to use edx instead of eax here because it might have been only made to
|
||||||
@ -849,11 +834,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
__ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
|
__ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
|
||||||
__ j(not_zero, &runtime);
|
__ j(not_zero, &runtime);
|
||||||
|
|
||||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||||
// Load offset into edi and replace subject string with parent.
|
// Load offset into edi and replace subject string with parent.
|
||||||
__ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
|
__ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
|
||||||
__ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
|
__ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
|
||||||
__ jmp(&check_underlying); // Go to (5a).
|
__ jmp(&check_underlying); // Go to (1).
|
||||||
#endif // V8_INTERPRETED_REGEXP
|
#endif // V8_INTERPRETED_REGEXP
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1150,21 +1135,26 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
__ bind(&runtime_call);
|
__ bind(&runtime_call);
|
||||||
|
|
||||||
// Push arguments below the return address.
|
|
||||||
__ pop(ecx);
|
|
||||||
__ push(edx);
|
|
||||||
__ push(eax);
|
|
||||||
|
|
||||||
// Figure out which native to call and setup the arguments.
|
|
||||||
if (cc == equal) {
|
if (cc == equal) {
|
||||||
__ push(ecx);
|
{
|
||||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ Push(edx);
|
||||||
|
__ Push(eax);
|
||||||
|
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||||
|
}
|
||||||
|
// Turn true into 0 and false into some non-zero value.
|
||||||
|
STATIC_ASSERT(EQUAL == 0);
|
||||||
|
__ sub(eax, Immediate(isolate()->factory()->true_value()));
|
||||||
|
__ Ret();
|
||||||
} else {
|
} else {
|
||||||
|
// Push arguments below the return address.
|
||||||
|
__ pop(ecx);
|
||||||
|
__ push(edx);
|
||||||
|
__ push(eax);
|
||||||
__ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
|
__ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
|
||||||
|
|
||||||
// Restore return address on the stack.
|
// Restore return address on the stack.
|
||||||
__ push(ecx);
|
__ push(ecx);
|
||||||
|
|
||||||
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
|
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
|
||||||
// tagged as a small integer.
|
// tagged as a small integer.
|
||||||
__ TailCallRuntime(Runtime::kCompare);
|
__ TailCallRuntime(Runtime::kCompare);
|
||||||
|
10
deps/v8/src/zone.cc
vendored
10
deps/v8/src/zone.cc
vendored
@ -105,7 +105,10 @@ void* Zone::New(size_t size) {
|
|||||||
Address result = position_;
|
Address result = position_;
|
||||||
|
|
||||||
const size_t size_with_redzone = size + kASanRedzoneBytes;
|
const size_t size_with_redzone = size + kASanRedzoneBytes;
|
||||||
if (limit_ < position_ + size_with_redzone) {
|
const uintptr_t limit = reinterpret_cast<uintptr_t>(limit_);
|
||||||
|
const uintptr_t position = reinterpret_cast<uintptr_t>(position_);
|
||||||
|
// position_ > limit_ can be true after the alignment correction above.
|
||||||
|
if (limit < position || size_with_redzone > limit - position) {
|
||||||
result = NewExpand(size_with_redzone);
|
result = NewExpand(size_with_redzone);
|
||||||
} else {
|
} else {
|
||||||
position_ += size_with_redzone;
|
position_ += size_with_redzone;
|
||||||
@ -222,7 +225,10 @@ Address Zone::NewExpand(size_t size) {
|
|||||||
// Make sure the requested size is already properly aligned and that
|
// Make sure the requested size is already properly aligned and that
|
||||||
// there isn't enough room in the Zone to satisfy the request.
|
// there isn't enough room in the Zone to satisfy the request.
|
||||||
DCHECK_EQ(size, RoundDown(size, kAlignment));
|
DCHECK_EQ(size, RoundDown(size, kAlignment));
|
||||||
DCHECK_LT(limit_, position_ + size);
|
DCHECK(limit_ < position_ ||
|
||||||
|
reinterpret_cast<uintptr_t>(limit_) -
|
||||||
|
reinterpret_cast<uintptr_t>(position_) <
|
||||||
|
size);
|
||||||
|
|
||||||
// Compute the new segment size. We use a 'high water mark'
|
// Compute the new segment size. We use a 'high water mark'
|
||||||
// strategy, where we increase the segment size every time we expand
|
// strategy, where we increase the segment size every time we expand
|
||||||
|
23
deps/v8/test/cctest/test-regexp.cc
vendored
23
deps/v8/test/cctest/test-regexp.cc
vendored
@ -1967,3 +1967,26 @@ TEST(UseCountRegExp) {
|
|||||||
CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]);
|
CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]);
|
||||||
CHECK(resultToStringError->IsObject());
|
CHECK(resultToStringError->IsObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UncachedExternalString
|
||||||
|
: public v8::String::ExternalOneByteStringResource {
|
||||||
|
public:
|
||||||
|
const char* data() const override { return "abcdefghijklmnopqrstuvwxyz"; }
|
||||||
|
size_t length() const override { return 26; }
|
||||||
|
bool IsCompressible() const override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(UncachedExternalString) {
|
||||||
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
LocalContext env;
|
||||||
|
v8::Local<v8::String> external =
|
||||||
|
v8::String::NewExternalOneByte(isolate, new UncachedExternalString())
|
||||||
|
.ToLocalChecked();
|
||||||
|
CHECK(v8::Utils::OpenHandle(*external)->map() ==
|
||||||
|
CcTest::i_isolate()->heap()->short_external_one_byte_string_map());
|
||||||
|
v8::Local<v8::Object> global = env->Global();
|
||||||
|
global->Set(env.local(), v8_str("external"), external).FromJust();
|
||||||
|
CompileRun("var re = /y(.)/; re.test('ab');");
|
||||||
|
ExpectString("external.substring(1).match(re)[1]", "z");
|
||||||
|
}
|
||||||
|
1
deps/v8/test/mjsunit/mjsunit.status
vendored
1
deps/v8/test/mjsunit/mjsunit.status
vendored
@ -862,7 +862,6 @@
|
|||||||
'array-literal-feedback': [FAIL],
|
'array-literal-feedback': [FAIL],
|
||||||
'undetectable-compare': [FAIL],
|
'undetectable-compare': [FAIL],
|
||||||
'debug-liveedit-2': [FAIL],
|
'debug-liveedit-2': [FAIL],
|
||||||
'compiler/deopt-tonumber-compare': [FAIL],
|
|
||||||
'es6/string-search': [FAIL],
|
'es6/string-search': [FAIL],
|
||||||
'es6/mirror-collections': [FAIL],
|
'es6/mirror-collections': [FAIL],
|
||||||
'es6/regress/regress-468661': [FAIL],
|
'es6/regress/regress-468661': [FAIL],
|
||||||
|
25
deps/v8/test/mjsunit/regress/regress-4788-1.js
vendored
Normal file
25
deps/v8/test/mjsunit/regress/regress-4788-1.js
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flags: --allow-natives-syntax
|
||||||
|
|
||||||
|
var f = (function() {
|
||||||
|
"use asm";
|
||||||
|
function foo(x) {
|
||||||
|
return x == 0;
|
||||||
|
}
|
||||||
|
return foo;
|
||||||
|
})();
|
||||||
|
|
||||||
|
function deopt(f) {
|
||||||
|
return {
|
||||||
|
toString : function() {
|
||||||
|
%DeoptimizeFunction(f);
|
||||||
|
return "2";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
%OptimizeFunctionOnNextCall(f);
|
||||||
|
assertFalse(f(deopt(f)));
|
25
deps/v8/test/mjsunit/regress/regress-4788-2.js
vendored
Normal file
25
deps/v8/test/mjsunit/regress/regress-4788-2.js
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flags: --allow-natives-syntax
|
||||||
|
|
||||||
|
var f = (function() {
|
||||||
|
"use asm";
|
||||||
|
function foo(x) {
|
||||||
|
return x < x;
|
||||||
|
}
|
||||||
|
return foo;
|
||||||
|
})();
|
||||||
|
|
||||||
|
function deopt(f) {
|
||||||
|
return {
|
||||||
|
toString : function() {
|
||||||
|
%DeoptimizeFunction(f);
|
||||||
|
return "2";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
%OptimizeFunctionOnNextCall(f);
|
||||||
|
assertFalse(f(deopt(f)));
|
82
deps/v8/test/mjsunit/regress/regress-crbug-594183.js
vendored
Normal file
82
deps/v8/test/mjsunit/regress/regress-crbug-594183.js
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flags: --allow-natives-syntax
|
||||||
|
|
||||||
|
var global = {}
|
||||||
|
|
||||||
|
var fish = [
|
||||||
|
{'name': 'foo'},
|
||||||
|
{'name': 'bar'},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < fish.length; i++) {
|
||||||
|
global[fish[i].name] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function load() {
|
||||||
|
var sum = 0;
|
||||||
|
for (var i = 0; i < fish.length; i++) {
|
||||||
|
var name = fish[i].name;
|
||||||
|
sum += global[name];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
load();
|
||||||
|
load();
|
||||||
|
%OptimizeFunctionOnNextCall(load);
|
||||||
|
load();
|
||||||
|
assertOptimized(load);
|
||||||
|
|
||||||
|
function store() {
|
||||||
|
for (var i = 0; i < fish.length; i++) {
|
||||||
|
var name = fish[i].name;
|
||||||
|
global[name] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
store();
|
||||||
|
store();
|
||||||
|
%OptimizeFunctionOnNextCall(store);
|
||||||
|
store();
|
||||||
|
assertOptimized(store);
|
||||||
|
|
||||||
|
// Regression test for KeyedStoreIC bug: would use PROPERTY mode erroneously.
|
||||||
|
|
||||||
|
function store_element(obj, key) {
|
||||||
|
obj[key] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var o1 = new Array(3);
|
||||||
|
var o2 = new Array(3);
|
||||||
|
o2.o2 = "o2";
|
||||||
|
var o3 = new Array(3);
|
||||||
|
o3.o3 = "o3";
|
||||||
|
var o4 = new Array(3);
|
||||||
|
o4.o4 = "o4";
|
||||||
|
var o5 = new Array(3);
|
||||||
|
o5.o5 = "o5";
|
||||||
|
// Make the KeyedStoreIC megamorphic.
|
||||||
|
store_element(o1, 0); // Premonomorphic
|
||||||
|
store_element(o1, 0); // Monomorphic
|
||||||
|
store_element(o2, 0); // 2-way polymorphic.
|
||||||
|
store_element(o3, 0); // 3-way polymorphic.
|
||||||
|
store_element(o4, 0); // 4-way polymorphic.
|
||||||
|
store_element(o5, 0); // Megamorphic.
|
||||||
|
|
||||||
|
function inferrable_store(key) {
|
||||||
|
store_element(o5, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
inferrable_store(0);
|
||||||
|
inferrable_store(0);
|
||||||
|
%OptimizeFunctionOnNextCall(inferrable_store);
|
||||||
|
inferrable_store(0);
|
||||||
|
assertOptimized(inferrable_store);
|
||||||
|
// If |inferrable_store| emitted a generic keyed store, it won't deopt upon
|
||||||
|
// seeing a property name key. It should have inferred a receiver map and
|
||||||
|
// emitted an elements store, however.
|
||||||
|
inferrable_store("deopt");
|
||||||
|
assertUnoptimized(inferrable_store);
|
28
deps/v8/test/mjsunit/regress/regress-crbug-605581.js
vendored
Normal file
28
deps/v8/test/mjsunit/regress/regress-crbug-605581.js
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flags: --expose-debug-as debug
|
||||||
|
|
||||||
|
var Debug = debug.Debug;
|
||||||
|
var exception = null;
|
||||||
|
|
||||||
|
function listener(event, exec_state, event_data, data) {
|
||||||
|
if (event != Debug.DebugEvent.Break) return;
|
||||||
|
try {
|
||||||
|
assertThrows(() => exec_state.frame(0).evaluate("bar.baz"), ReferenceError);
|
||||||
|
} catch (e) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.setListener(listener);
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
debugger; // bar is still in TDZ at this point.
|
||||||
|
let bar = 1;
|
||||||
|
(x => bar); // force bar to be context-allocated.
|
||||||
|
})();
|
||||||
|
|
||||||
|
Debug.setListener(null);
|
||||||
|
assertNull(exception);
|
5
deps/v8/test/mjsunit/regress/regress-v8-4972.js
vendored
Normal file
5
deps/v8/test/mjsunit/regress/regress-v8-4972.js
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
new class extends new Proxy(class {},{}) {}
|
1
deps/v8/test/mjsunit/undetectable-compare.js
vendored
1
deps/v8/test/mjsunit/undetectable-compare.js
vendored
@ -92,5 +92,4 @@ for (var i = 0; i < 5; i++) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
assertFalse(undetectable == %GetUndetectable());
|
|
||||||
assertFalse(undetectable === %GetUndetectable());
|
assertFalse(undetectable === %GetUndetectable());
|
||||||
|
@ -23,12 +23,6 @@ class RuntimeInterpreterTest : public TestWithIsolateAndZone {
|
|||||||
|
|
||||||
bool TestOperatorWithObjects(RuntimeMethod method, Handle<Object> lhs,
|
bool TestOperatorWithObjects(RuntimeMethod method, Handle<Object> lhs,
|
||||||
Handle<Object> rhs, bool expected);
|
Handle<Object> rhs, bool expected);
|
||||||
bool TestOperator(RuntimeMethod method, int32_t lhs, int32_t rhs,
|
|
||||||
bool expected);
|
|
||||||
bool TestOperator(RuntimeMethod method, double lhs, double rhs,
|
|
||||||
bool expected);
|
|
||||||
bool TestOperator(RuntimeMethod method, const char* lhs, const char* rhs,
|
|
||||||
bool expected);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -44,99 +38,6 @@ bool RuntimeInterpreterTest::TestOperatorWithObjects(RuntimeMethod method,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, int32_t lhs,
|
|
||||||
int32_t rhs, bool expected) {
|
|
||||||
Handle<Object> x = isolate()->factory()->NewNumberFromInt(lhs);
|
|
||||||
Handle<Object> y = isolate()->factory()->NewNumberFromInt(rhs);
|
|
||||||
return TestOperatorWithObjects(method, x, y, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, double lhs,
|
|
||||||
double rhs, bool expected) {
|
|
||||||
Handle<Object> x = isolate()->factory()->NewNumber(lhs);
|
|
||||||
Handle<Object> y = isolate()->factory()->NewNumber(rhs);
|
|
||||||
CHECK_EQ(HeapNumber::cast(*x)->value(), lhs);
|
|
||||||
CHECK_EQ(HeapNumber::cast(*y)->value(), rhs);
|
|
||||||
return TestOperatorWithObjects(method, x, y, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, const char* lhs,
|
|
||||||
const char* rhs, bool expected) {
|
|
||||||
Handle<Object> x = isolate()->factory()->NewStringFromAsciiChecked(lhs);
|
|
||||||
Handle<Object> y = isolate()->factory()->NewStringFromAsciiChecked(rhs);
|
|
||||||
return TestOperatorWithObjects(method, x, y, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST_F(RuntimeInterpreterTest, TestOperatorsWithIntegers) {
|
|
||||||
int32_t inputs[] = {kMinInt, Smi::kMinValue, -17, -1, 0, 1,
|
|
||||||
991, Smi::kMaxValue, kMaxInt};
|
|
||||||
TRACED_FOREACH(int, lhs, inputs) {
|
|
||||||
TRACED_FOREACH(int, rhs, inputs) {
|
|
||||||
#define INTEGER_OPERATOR_CHECK(r, op, x, y) \
|
|
||||||
CHECK(TestOperator(Runtime_Interpreter##r, x, y, x op y))
|
|
||||||
INTEGER_OPERATOR_CHECK(Equals, ==, lhs, rhs);
|
|
||||||
INTEGER_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
|
|
||||||
INTEGER_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
|
|
||||||
INTEGER_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
|
|
||||||
INTEGER_OPERATOR_CHECK(LessThan, <, lhs, rhs);
|
|
||||||
INTEGER_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
|
|
||||||
INTEGER_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
|
|
||||||
INTEGER_OPERATOR_CHECK(GreaterThanOrEqual, >=, lhs, rhs);
|
|
||||||
#undef INTEGER_OPERATOR_CHECK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST_F(RuntimeInterpreterTest, TestOperatorsWithDoubles) {
|
|
||||||
double inputs[] = {std::numeric_limits<double>::min(),
|
|
||||||
std::numeric_limits<double>::max(),
|
|
||||||
-0.001,
|
|
||||||
0.01,
|
|
||||||
3.14,
|
|
||||||
-6.02214086e23};
|
|
||||||
TRACED_FOREACH(double, lhs, inputs) {
|
|
||||||
TRACED_FOREACH(double, rhs, inputs) {
|
|
||||||
#define DOUBLE_OPERATOR_CHECK(r, op, x, y) \
|
|
||||||
CHECK(TestOperator(Runtime_Interpreter##r, x, y, x op y))
|
|
||||||
DOUBLE_OPERATOR_CHECK(Equals, ==, lhs, rhs);
|
|
||||||
DOUBLE_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
|
|
||||||
DOUBLE_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
|
|
||||||
DOUBLE_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
|
|
||||||
DOUBLE_OPERATOR_CHECK(LessThan, <, lhs, rhs);
|
|
||||||
DOUBLE_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
|
|
||||||
DOUBLE_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
|
|
||||||
DOUBLE_OPERATOR_CHECK(GreaterThanOrEqual, >=, lhs, rhs);
|
|
||||||
#undef DOUBLE_OPERATOR_CHECK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST_F(RuntimeInterpreterTest, TestOperatorsWithString) {
|
|
||||||
const char* inputs[] = {"abc", "a", "def", "0"};
|
|
||||||
TRACED_FOREACH(const char*, lhs, inputs) {
|
|
||||||
TRACED_FOREACH(const char*, rhs, inputs) {
|
|
||||||
#define STRING_OPERATOR_CHECK(r, op, x, y) \
|
|
||||||
CHECK(TestOperator(Runtime_Interpreter##r, x, y, \
|
|
||||||
std::string(x) op std::string(y)))
|
|
||||||
STRING_OPERATOR_CHECK(Equals, ==, lhs, rhs);
|
|
||||||
STRING_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
|
|
||||||
STRING_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
|
|
||||||
STRING_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
|
|
||||||
STRING_OPERATOR_CHECK(LessThan, <, lhs, rhs);
|
|
||||||
STRING_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
|
|
||||||
STRING_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
|
|
||||||
STRING_OPERATOR_CHECK(GreaterThanOrEqual, >=, lhs, rhs);
|
|
||||||
#undef STRING_OPERATOR_CHECK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST_F(RuntimeInterpreterTest, ToBoolean) {
|
TEST_F(RuntimeInterpreterTest, ToBoolean) {
|
||||||
double quiet_nan = std::numeric_limits<double>::quiet_NaN();
|
double quiet_nan = std::numeric_limits<double>::quiet_NaN();
|
||||||
std::pair<Handle<Object>, bool> cases[] = {
|
std::pair<Handle<Object>, bool> cases[] = {
|
||||||
|
2
deps/v8/tools/gen-postmortem-metadata.py
vendored
2
deps/v8/tools/gen-postmortem-metadata.py
vendored
@ -92,6 +92,8 @@ consts_misc = [
|
|||||||
'value': 'DescriptorArray::kFirstIndex' },
|
'value': 'DescriptorArray::kFirstIndex' },
|
||||||
{ 'name': 'prop_type_field',
|
{ 'name': 'prop_type_field',
|
||||||
'value': 'DATA' },
|
'value': 'DATA' },
|
||||||
|
{ 'name': 'prop_type_const_field',
|
||||||
|
'value': 'DATA_CONSTANT' },
|
||||||
{ 'name': 'prop_type_mask',
|
{ 'name': 'prop_type_mask',
|
||||||
'value': 'PropertyDetails::TypeField::kMask' },
|
'value': 'PropertyDetails::TypeField::kMask' },
|
||||||
{ 'name': 'prop_index_mask',
|
{ 'name': 'prop_index_mask',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user