From a6ca5e559a6f11307b9c65b14c7a93584e4c8b86 Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Wed, 4 May 2016 16:46:17 +0200 Subject: [PATCH] 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 Reviewed-By: JungMinu - Minwoo Jung --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/arm/code-stubs-arm.cc | 81 ++++++------ deps/v8/src/arm64/code-stubs-arm64.cc | 94 +++++++------- .../ia32/instruction-selector-ia32.cc | 3 +- deps/v8/src/compiler/js-generic-lowering.cc | 118 ++---------------- deps/v8/src/compiler/js-generic-lowering.h | 1 - .../compiler/x64/instruction-selector-x64.cc | 7 +- deps/v8/src/debug/debug-evaluate.cc | 1 + deps/v8/src/ia32/code-stubs-ia32.cc | 100 +++++++-------- deps/v8/src/ic/ic.cc | 30 +++-- deps/v8/src/ic/ic.h | 20 +-- deps/v8/src/interpreter/interpreter.cc | 16 +-- deps/v8/src/isolate.cc | 2 + deps/v8/src/mips/code-stubs-mips.cc | 85 ++++++------- deps/v8/src/mips64/code-stubs-mips64.cc | 97 +++++++------- deps/v8/src/objects-inl.h | 4 + deps/v8/src/objects.cc | 20 ++- deps/v8/src/objects.h | 3 - deps/v8/src/ppc/code-stubs-ppc.cc | 82 ++++++------ deps/v8/src/runtime/runtime-interpreter.cc | 103 --------------- deps/v8/src/runtime/runtime-object.cc | 22 ---- deps/v8/src/runtime/runtime-operators.cc | 76 +++++++++++ deps/v8/src/runtime/runtime.h | 20 ++- deps/v8/src/type-feedback-vector.cc | 33 ++++- deps/v8/src/type-feedback-vector.h | 4 + deps/v8/src/type-info.cc | 2 +- deps/v8/src/x64/code-stubs-x64.cc | 95 +++++++------- deps/v8/src/x87/code-stubs-x87.cc | 98 +++++++-------- deps/v8/src/zone.cc | 10 +- deps/v8/test/cctest/test-regexp.cc | 23 ++++ deps/v8/test/mjsunit/mjsunit.status | 1 - .../v8/test/mjsunit/regress/regress-4788-1.js | 25 ++++ .../v8/test/mjsunit/regress/regress-4788-2.js | 25 ++++ .../mjsunit/regress/regress-crbug-594183.js | 82 ++++++++++++ .../mjsunit/regress/regress-crbug-605581.js | 28 +++++ .../test/mjsunit/regress/regress-v8-4972.js | 5 + deps/v8/test/mjsunit/undetectable-compare.js | 1 - .../runtime/runtime-interpreter-unittest.cc | 99 --------------- deps/v8/tools/gen-postmortem-metadata.py | 2 + 39 files changed, 736 insertions(+), 784 deletions(-) create mode 100644 deps/v8/test/mjsunit/regress/regress-4788-1.js create mode 100644 deps/v8/test/mjsunit/regress/regress-4788-2.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-594183.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-605581.js create mode 100644 deps/v8/test/mjsunit/regress/regress-v8-4972.js diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 130a93c05edd61..cde8bf192dd6fc 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 5 #define V8_MINOR_VERSION 0 #define V8_BUILD_NUMBER 71 -#define V8_PATCH_LEVEL 35 +#define V8_PATCH_LEVEL 47 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc index 239eddd28efddd..82fb51d2f192da 100644 --- a/deps/v8/src/arm/code-stubs-arm.cc +++ b/deps/v8/src/arm/code-stubs-arm.cc @@ -671,11 +671,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { __ bind(&slow); - __ Push(lhs, rhs); - // Figure out which native to call and setup the arguments. 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 { + __ Push(lhs, rhs); int ncr; // NaN compare result if (cc == lt || cc == le) { ncr = GREATER; @@ -1573,34 +1581,33 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ ldr(subject, MemOperand(sp, kSubjectOffset)); __ JumpIfSmi(subject, &runtime); __ 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 // r3: subject string - // r0: subject string instance type // regexp_data: RegExp data (FixedArray) // Handle subject string according to its encoding and representation: - // (1) Sequential string? If yes, go to (5). - // (2) Anything but sequential or cons? If yes, go to (6). - // (3) Cons string. If the string is flat, replace subject with first string. - // Otherwise bailout. - // (4) Is subject external? If yes, go to (7). - // (5) Sequential string. Load regexp code according to encoding. + // (1) Sequential string? If yes, go to (4). + // (2) Sequential or cons? If not, go to (5). + // (3) Cons string. If the string is flat, replace subject with first string + // and go to (1). Otherwise bail out to runtime. + // (4) Sequential string. Load regexp code according to encoding. // (E) Carry on. /// [...] // Deferred code at the end of the stub: - // (6) Not a long external string? If yes, go to (8). - // (7) External string. Make it, offset-wise, look like a sequential string. - // Go to (5). - // (8) Short external string or not a string? If yes, bail out to runtime. - // (9) Sliced string. Replace subject with parent. Go to (4). + // (5) Long external string? If not, go to (7). + // (6) External string. Make it, offset-wise, look like a sequential string. + // Go to (4). + // (7) Short external string or not a string? If yes, bail out to runtime. + // (8) Sliced string. Replace subject with parent. Go to (1). - Label seq_string /* 5 */, external_string /* 7 */, - check_underlying /* 4 */, not_seq_nor_cons /* 6 */, - not_long_external /* 8 */; + Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */, + not_seq_nor_cons /* 5 */, not_long_external /* 7 */; - // (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, r0, Operand(kIsNotStringMask | @@ -1608,15 +1615,15 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { kShortExternalStringMask), SetCC); 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(kSlicedStringTag > kExternalStringTag); STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); STATIC_ASSERT(kShortExternalStringTag > 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. // Replace subject with first string and reload instance type. @@ -1624,19 +1631,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ CompareRoot(r0, Heap::kempty_stringRootIndex); __ b(ne, &runtime); __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); + __ jmp(&check_underlying); - // (4) Is subject external? If yes, go to (7). - __ 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. + // (4) Sequential string. Load regexp code according to encoding. __ bind(&seq_string); // subject: sequential subject string (or look-alike, external string) // r3: original subject string @@ -1869,12 +1866,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kRegExpExec); // 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); // 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); __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); @@ -1891,15 +1888,15 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ sub(subject, subject, 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); STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask)); __ 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. __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); __ SmiUntag(r9); diff --git a/deps/v8/src/arm64/code-stubs-arm64.cc b/deps/v8/src/arm64/code-stubs-arm64.cc index 57a0ffde92128c..ad566e68fc2073 100644 --- a/deps/v8/src/arm64/code-stubs-arm64.cc +++ b/deps/v8/src/arm64/code-stubs-arm64.cc @@ -628,11 +628,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { __ Bind(&slow); - __ Push(lhs, rhs); - // Figure out which native to call and setup the arguments. 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 { + __ Push(lhs, rhs); int ncr; // NaN compare result if ((cond == lt) || (cond == le)) { ncr = GREATER; @@ -1739,35 +1747,35 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ Peek(subject, kSubjectOffset); __ JumpIfSmi(subject, &runtime); - __ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset)); - __ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset)); - __ Ldr(jsstring_length, FieldMemOperand(subject, String::kLengthOffset)); // Handle subject string according to its encoding and representation: - // (1) Sequential string? If yes, go to (5). - // (2) Anything but sequential or cons? If yes, go to (6). - // (3) Cons string. If the string is flat, replace subject with first string. - // Otherwise bailout. - // (4) Is subject external? If yes, go to (7). - // (5) Sequential string. Load regexp code according to encoding. + // (1) Sequential string? If yes, go to (4). + // (2) Sequential or cons? If not, go to (5). + // (3) Cons string. If the string is flat, replace subject with first string + // and go to (1). Otherwise bail out to runtime. + // (4) Sequential string. Load regexp code according to encoding. // (E) Carry on. /// [...] // Deferred code at the end of the stub: - // (6) Not a long external string? If yes, go to (8). - // (7) External string. Make it, offset-wise, look like a sequential string. - // Go to (5). - // (8) Short external string or not a string? If yes, bail out to runtime. - // (9) Sliced string. Replace subject with parent. Go to (4). - - Label check_underlying; // (4) - Label seq_string; // (5) - Label not_seq_nor_cons; // (6) - Label external_string; // (7) - Label not_long_external; // (8) - - // (1) Sequential string? If yes, go to (5). + // (5) Long external string? If not, go to (7). + // (6) External string. Make it, offset-wise, look like a sequential string. + // Go to (4). + // (7) Short external string or not a string? If yes, bail out to runtime. + // (8) Sliced string. Replace subject with parent. Go to (1). + + Label check_underlying; // (1) + Label seq_string; // (4) + Label not_seq_nor_cons; // (5) + Label external_string; // (6) + Label not_long_external; // (7) + + __ 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, string_type, kIsNotStringMask | @@ -1784,36 +1792,24 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { // is a String STATIC_ASSERT((kStringTag | kSeqStringTag) == 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(kSlicedStringTag > kExternalStringTag); STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); STATIC_ASSERT(kShortExternalStringTag > 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. __ Ldr(x10, FieldMemOperand(subject, ConsString::kSecondOffset)); __ JumpIfNotRoot(x10, Heap::kempty_stringRootIndex, &runtime); // Replace subject with first string. __ Ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); + __ B(&check_underlying); - // (4) Is subject external? If yes, go to (7). - __ 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. + // (4) Sequential string. Load regexp code according to encoding. __ Bind(&seq_string); // 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); // 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); // 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); if (masm->emit_debug_code()) { // 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. STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); __ 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. __ Bind(¬_long_external); STATIC_ASSERT(kShortExternalStringTag != 0); @@ -2116,11 +2112,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { kShortExternalStringMask | kIsNotStringMask, &runtime); - // (9) Sliced string. Replace subject with parent. + // (8) Sliced string. Replace subject with parent. __ Ldr(sliced_string_offset, UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset)); __ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); - __ B(&check_underlying); // Go to (4). + __ B(&check_underlying); // Go to (1). #endif } diff --git a/deps/v8/src/compiler/ia32/instruction-selector-ia32.cc b/deps/v8/src/compiler/ia32/instruction-selector-ia32.cc index d821462526caa0..f649ba91099908 100644 --- a/deps/v8/src/compiler/ia32/instruction-selector-ia32.cc +++ b/deps/v8/src/compiler/ia32/instruction-selector-ia32.cc @@ -530,9 +530,10 @@ void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { IA32OperandGenerator g(selector); + InstructionOperand temps[] = {g.TempRegister(eax)}; selector->Emit(opcode, g.DefineAsFixed(node, edx), 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, diff --git a/deps/v8/src/compiler/js-generic-lowering.cc b/deps/v8/src/compiler/js-generic-lowering.cc index b6cd40d21df56e..df2d9086efef37 100644 --- a/deps/v8/src/compiler/js-generic-lowering.cc +++ b/deps/v8/src/compiler/js-generic-lowering.cc @@ -81,117 +81,22 @@ REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV) REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD) #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) \ void JSGenericLowering::Lower##op(Node* node) { \ 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(JSCreateModuleContext, Runtime::kPushModuleContext) REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver) -#undef REPLACE_RUNTIME - - -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(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)); -} - +#undef REPLACE_RUNTIME_CALL void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, CallDescriptor::Flags flags) { @@ -207,11 +112,12 @@ void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, void JSGenericLowering::ReplaceWithRuntimeCall(Node* node, Runtime::FunctionId f, int nargs_override) { + CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); Operator::Properties properties = node->op()->properties(); const Runtime::Function* fun = Runtime::FunctionForId(f); int nargs = (nargs_override < 0) ? fun->nargs : nargs_override; - CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( - zone(), f, nargs, properties, CallDescriptor::kNeedsFrameState); + CallDescriptor* desc = + Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags); Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate())); Node* arity = jsgraph()->Int32Constant(nargs); node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size)); diff --git a/deps/v8/src/compiler/js-generic-lowering.h b/deps/v8/src/compiler/js-generic-lowering.h index f4acdf63056eac..5ee759bcc8c458 100644 --- a/deps/v8/src/compiler/js-generic-lowering.h +++ b/deps/v8/src/compiler/js-generic-lowering.h @@ -36,7 +36,6 @@ class JSGenericLowering final : public Reducer { #undef DECLARE_LOWER // 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 ReplaceWithRuntimeCall(Node* node, Runtime::FunctionId f, int args = -1); diff --git a/deps/v8/src/compiler/x64/instruction-selector-x64.cc b/deps/v8/src/compiler/x64/instruction-selector-x64.cc index ac0c7f7bf2fec9..d3a2a8e7533672 100644 --- a/deps/v8/src/compiler/x64/instruction-selector-x64.cc +++ b/deps/v8/src/compiler/x64/instruction-selector-x64.cc @@ -763,9 +763,10 @@ void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { X64OperandGenerator g(selector); - selector->Emit(opcode, g.DefineAsFixed(node, rdx), - g.UseFixed(node->InputAt(0), rax), - g.UseUniqueRegister(node->InputAt(1))); + InstructionOperand temps[] = {g.TempRegister(rax)}; + selector->Emit( + opcode, g.DefineAsFixed(node, rdx), g.UseFixed(node->InputAt(0), rax), + g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps); } } // namespace diff --git a/deps/v8/src/debug/debug-evaluate.cc b/deps/v8/src/debug/debug-evaluate.cc index 1134c9dd68ae9c..8114c21fe85684 100644 --- a/deps/v8/src/debug/debug-evaluate.cc +++ b/deps/v8/src/debug/debug-evaluate.cc @@ -346,6 +346,7 @@ void DebugEvaluate::ContextBuilder::MaterializeContextChain( // within debug-evaluate. continue; } + if (value->IsTheHole()) continue; // Value is not initialized yet (in TDZ). JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check(); } } diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc index 2565c45d310f7b..510b58e723506d 100644 --- a/deps/v8/src/ia32/code-stubs-ia32.cc +++ b/deps/v8/src/ia32/code-stubs-ia32.cc @@ -798,39 +798,37 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ mov(eax, Operand(esp, kSubjectOffset)); __ JumpIfSmi(eax, &runtime); __ 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 // edx: subject string - // ebx: subject string instance type // ecx: RegExp data (FixedArray) // Handle subject string according to its encoding and representation: // (1) Sequential two byte? If yes, go to (9). - // (2) Sequential one byte? If yes, go to (6). - // (3) Anything but sequential or cons? If yes, go to (7). - // (4) Cons string. If the string is flat, replace subject with first string. - // Otherwise bailout. - // (5a) Is subject sequential two byte? If yes, go to (9). - // (5b) Is subject external? If yes, go to (8). - // (6) One byte sequential. Load regexp code for one byte. + // (2) Sequential one byte? If yes, go to (5). + // (3) Sequential or cons? If not, go to (6). + // (4) Cons string. If the string is flat, replace subject with first string + // and go to (1). Otherwise bail out to runtime. + // (5) One byte sequential. Load regexp code for one byte. // (E) Carry on. /// [...] // Deferred code at the end of the stub: - // (7) Not a long external string? If yes, go to (10). - // (8) External string. Make it, offset-wise, look like a sequential string. - // (8a) Is the external string one byte? If yes, go to (6). - // (9) Two byte sequential. Load regexp code for one byte. Go to (E). + // (6) Long external string? If not, go to (10). + // (7) External string. Make it, offset-wise, look like a sequential string. + // (8) Is the external string one byte? If yes, go to (5). + // (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. - // (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 */, - external_string /* 8 */, check_underlying /* 5a */, - not_seq_nor_cons /* 7 */, check_code /* E */, - not_long_external /* 10 */; + Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */, + external_string /* 7 */, check_underlying /* 1 */, + not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */; + __ bind(&check_underlying); // (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 | kStringRepresentationMask | kStringEncodingMask | @@ -838,14 +836,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); __ 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. __ and_(ebx, Immediate(kIsNotStringMask | kStringRepresentationMask | 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 // have already been covered. STATIC_ASSERT(kConsStringTag < kExternalStringTag); @@ -853,32 +851,19 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); STATIC_ASSERT(kShortExternalStringTag > 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. // Replace subject with first string and reload instance type. __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string()); __ j(not_equal, &runtime); __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); - __ bind(&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). + __ jmp(&check_underlying); // eax: sequential subject string (or look-alike, external string) // edx: original subject string // 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); // 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 @@ -1105,12 +1090,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kRegExpExec); // 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); // Compare flags are still set from (3). __ 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); // Reload instance type. __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); @@ -1126,14 +1111,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 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); - __ 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) // edx: original subject string // 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); // 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 @@ -1153,11 +1138,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag)); __ 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. __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset)); __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset)); - __ jmp(&check_underlying); // Go to (5a). + __ jmp(&check_underlying); // Go to (1). #endif // V8_INTERPRETED_REGEXP } @@ -1442,21 +1427,24 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { } __ 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) { - __ 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 { + // Push arguments below the return address. + __ pop(ecx); + __ push(edx); + __ push(eax); __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); - - // Restore return address on the stack. __ push(ecx); - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) // tagged as a small integer. __ TailCallRuntime(Runtime::kCompare); diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc index 4c2b20ca1b84b9..c0b3e49338a499 100644 --- a/deps/v8/src/ic/ic.cc +++ b/deps/v8/src/ic/ic.cc @@ -573,13 +573,21 @@ static bool MigrateDeprecated(Handle object) { return true; } - -void IC::ConfigureVectorState(IC::State new_state) { +void IC::ConfigureVectorState(IC::State new_state, Handle key) { DCHECK(UseVector()); if (new_state == PREMONOMORPHIC) { nexus()->ConfigurePremonomorphic(); } 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(); + nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); + } else { + DCHECK(kind() == Code::KEYED_STORE_IC); + KeyedStoreICNexus* nexus = casted_nexus(); + nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); + } } else { UNREACHABLE(); } @@ -662,7 +670,7 @@ MaybeHandle LoadIC::Load(Handle object, Handle name) { // Rewrite to the generic keyed load stub. if (FLAG_use_ic) { DCHECK(UseVector()); - ConfigureVectorState(MEGAMORPHIC); + ConfigureVectorState(MEGAMORPHIC, name); TRACE_IC("LoadIC", name); TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); } @@ -853,7 +861,7 @@ void IC::PatchCache(Handle name, Handle code) { CopyICToMegamorphicCache(name); } if (UseVector()) { - ConfigureVectorState(MEGAMORPHIC); + ConfigureVectorState(MEGAMORPHIC, name); } else { set_target(*megamorphic_stub()); } @@ -1012,7 +1020,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { if (state() == UNINITIALIZED) { // This is the first time we execute this inline cache. Set the target to // the pre monomorphic stub to delay setting the monomorphic state. - ConfigureVectorState(PREMONOMORPHIC); + ConfigureVectorState(PREMONOMORPHIC, Handle()); TRACE_IC("LoadIC", lookup->name()); return; } @@ -1378,7 +1386,7 @@ MaybeHandle KeyedLoadIC::Load(Handle object, if (!is_vector_set() || stub.is_null()) { Code* generic = *megamorphic_stub(); if (!stub.is_null() && *stub == generic) { - ConfigureVectorState(MEGAMORPHIC); + ConfigureVectorState(MEGAMORPHIC, key); TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); } @@ -1471,7 +1479,7 @@ MaybeHandle StoreIC::Store(Handle object, Handle name, // Rewrite to the generic keyed store stub. if (FLAG_use_ic) { if (UseVector()) { - ConfigureVectorState(MEGAMORPHIC); + ConfigureVectorState(MEGAMORPHIC, name); } else if (!AddressIsDeoptimizedCode()) { set_target(*megamorphic_stub()); } @@ -1645,7 +1653,7 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle value, if (state() == UNINITIALIZED) { // This is the first time we execute this inline cache. Set the target to // the pre monomorphic stub to delay setting the monomorphic state. - ConfigureVectorState(PREMONOMORPHIC); + ConfigureVectorState(PREMONOMORPHIC, Handle()); TRACE_IC("StoreIC", lookup->name()); return; } @@ -2072,7 +2080,7 @@ MaybeHandle KeyedStoreIC::Store(Handle object, JSReceiver::MAY_BE_STORE_FROM_KEYED), Object); if (!is_vector_set()) { - ConfigureVectorState(MEGAMORPHIC); + ConfigureVectorState(MEGAMORPHIC, key); TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "unhandled internalized string key"); TRACE_IC("StoreIC", key); @@ -2147,7 +2155,7 @@ MaybeHandle KeyedStoreIC::Store(Handle object, if (!is_vector_set() || stub.is_null()) { Code* megamorphic = *megamorphic_stub(); if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { - ConfigureVectorState(MEGAMORPHIC); + ConfigureVectorState(MEGAMORPHIC, key); TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", *stub == megamorphic ? "set generic" : "slow stub"); } diff --git a/deps/v8/src/ic/ic.h b/deps/v8/src/ic/ic.h index 2ce182b76e4ede..0a324a82056d92 100644 --- a/deps/v8/src/ic/ic.h +++ b/deps/v8/src/ic/ic.h @@ -112,7 +112,7 @@ class IC { } // Configure for most states. - void ConfigureVectorState(IC::State new_state); + void ConfigureVectorState(IC::State new_state, Handle key); // Configure the vector for MONOMORPHIC. void ConfigureVectorState(Handle name, Handle map, Handle handler); @@ -296,10 +296,6 @@ class CallIC : public IC { class LoadIC : public IC { public: - static ExtraICState ComputeExtraICState(TypeofMode typeof_mode) { - return LoadICState(typeof_mode).GetExtraICState(); - } - TypeofMode typeof_mode() const { return LoadICState::GetTypeofMode(extra_ic_state()); } @@ -364,20 +360,6 @@ class LoadIC : public IC { class KeyedLoadIC : public LoadIC { public: - // ExtraICState bits (building on IC) - class IcCheckTypeField - : public BitField {}; - - 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, KeyedLoadICNexus* nexus = NULL) : LoadIC(depth, isolate, nexus) { diff --git a/deps/v8/src/interpreter/interpreter.cc b/deps/v8/src/interpreter/interpreter.cc index 43a7ead2810e14..eb883427bbabb5 100644 --- a/deps/v8/src/interpreter/interpreter.cc +++ b/deps/v8/src/interpreter/interpreter.cc @@ -1139,7 +1139,7 @@ void Interpreter::DoNewWide(InterpreterAssembler* assembler) { // // Test if the value in the register equals the accumulator. 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 register is not equal to the accumulator. 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 register is strictly equal to the accumulator. 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 register is not strictly equal to the // accumulator. 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 register is less than the accumulator. 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 register is greater than the accumulator. 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 register is less than or equal to the // accumulator. 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 register is greater than or equal to the // accumulator. void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kInterpreterGreaterThanOrEqual, assembler); + DoBinaryOp(Runtime::kGreaterThanOrEqual, assembler); } diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc index 8eb8b71b393479..8116f14d30260a 100644 --- a/deps/v8/src/isolate.cc +++ b/deps/v8/src/isolate.cc @@ -2512,6 +2512,7 @@ bool Isolate::IsFastArrayConstructorPrototypeChainIntact() { } bool Isolate::IsArraySpeciesLookupChainIntact() { + if (!FLAG_harmony_species) return true; // 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 // what the protector stands for: @@ -2530,6 +2531,7 @@ bool Isolate::IsArraySpeciesLookupChainIntact() { } void Isolate::InvalidateArraySpeciesProtector() { + if (!FLAG_harmony_species) return; DCHECK(factory()->species_protector()->value()->IsSmi()); DCHECK(IsArraySpeciesLookupChainIntact()); PropertyCell::SetValueWithInvalidation( diff --git a/deps/v8/src/mips/code-stubs-mips.cc b/deps/v8/src/mips/code-stubs-mips.cc index 77dbcb122d4dfc..541e73e2fa407e 100644 --- a/deps/v8/src/mips/code-stubs-mips.cc +++ b/deps/v8/src/mips/code-stubs-mips.cc @@ -718,13 +718,21 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { // Never falls through to here. __ 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) { - __ 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 { + // Prepare for call to builtin. Push object pointers, a0 (lhs) first, + // a1 (rhs) second. + __ Push(lhs, rhs); int ncr; // NaN compare result. if (cc == lt || cc == le) { ncr = GREATER; @@ -1597,7 +1605,6 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); } - void RegExpExecStub::Generate(MacroAssembler* masm) { // 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 @@ -1630,8 +1637,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { // Ensure that a RegExp stack is allocated. ExternalReference address_of_regexp_stack_memory_address = - ExternalReference::address_of_regexp_stack_memory_address( - isolate()); + ExternalReference::address_of_regexp_stack_memory_address(isolate()); ExternalReference address_of_regexp_stack_memory_size = ExternalReference::address_of_regexp_stack_memory_size(isolate()); __ li(a0, Operand(address_of_regexp_stack_memory_size)); @@ -1683,34 +1689,33 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ lw(subject, MemOperand(sp, kSubjectOffset)); __ JumpIfSmi(subject, &runtime); __ 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 // a3: subject string - // a0: subject string instance type // regexp_data: RegExp data (FixedArray) // Handle subject string according to its encoding and representation: - // (1) Sequential string? If yes, go to (5). - // (2) Anything but sequential or cons? If yes, go to (6). - // (3) Cons string. If the string is flat, replace subject with first string. - // Otherwise bailout. - // (4) Is subject external? If yes, go to (7). - // (5) Sequential string. Load regexp code according to encoding. + // (1) Sequential string? If yes, go to (4). + // (2) Sequential or cons? If not, go to (5). + // (3) Cons string. If the string is flat, replace subject with first string + // and go to (1). Otherwise bail out to runtime. + // (4) Sequential string. Load regexp code according to encoding. // (E) Carry on. /// [...] // Deferred code at the end of the stub: - // (6) Not a long external string? If yes, go to (8). - // (7) External string. Make it, offset-wise, look like a sequential string. - // Go to (5). - // (8) Short external string or not a string? If yes, bail out to runtime. - // (9) Sliced string. Replace subject with parent. Go to (4). + // (5) Long external string? If not, go to (7). + // (6) External string. Make it, offset-wise, look like a sequential string. + // Go to (4). + // (7) Short external string or not a string? If yes, bail out to runtime. + // (8) Sliced string. Replace subject with parent. Go to (1). + + Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */, + not_seq_nor_cons /* 5 */, not_long_external /* 7 */; - Label seq_string /* 5 */, external_string /* 7 */, - check_underlying /* 4 */, not_seq_nor_cons /* 6 */, - not_long_external /* 8 */; + __ bind(&check_underlying); + __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); + __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); - // (1) Sequential string? If yes, go to (5). + // (1) Sequential string? If yes, go to (4). __ And(a1, a0, Operand(kIsNotStringMask | @@ -1719,12 +1724,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); __ 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(kSlicedStringTag > kExternalStringTag); STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); - // Go to (6). + // Go to (5). __ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag)); // (3) Cons string. Check that it's flat. @@ -1733,19 +1738,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ LoadRoot(a1, Heap::kempty_stringRootIndex); __ Branch(&runtime, ne, a0, Operand(a1)); __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); + __ jmp(&check_underlying); - // (4) Is subject external? If yes, go to (7). - __ 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. + // (4) Sequential string. Load regexp code according to encoding. __ bind(&seq_string); // subject: sequential subject string (or look-alike, external string) // a3: original subject string @@ -1987,12 +1982,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kRegExpExec); // 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); - // Go to (8). + // Go to (7). __ 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); __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); @@ -2014,13 +2009,13 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { SeqTwoByteString::kHeaderSize - kHeapObjectTag); __ 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); STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask)); __ 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. __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); __ sra(t0, t0, kSmiTagSize); diff --git a/deps/v8/src/mips64/code-stubs-mips64.cc b/deps/v8/src/mips64/code-stubs-mips64.cc index bde5531077cc4e..28812ad9973219 100644 --- a/deps/v8/src/mips64/code-stubs-mips64.cc +++ b/deps/v8/src/mips64/code-stubs-mips64.cc @@ -715,13 +715,21 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { // Never falls through to here. __ 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) { - __ 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 { + // Prepare for call to builtin. Push object pointers, a0 (lhs) first, + // a1 (rhs) second. + __ Push(lhs, rhs); int ncr; // NaN compare result. if (cc == lt || cc == le) { ncr = GREATER; @@ -1678,50 +1686,51 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ ld(subject, MemOperand(sp, kSubjectOffset)); __ JumpIfSmi(subject, &runtime); __ 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 // a3: subject string - // a0: subject string instance type // regexp_data: RegExp data (FixedArray) // Handle subject string according to its encoding and representation: - // (1) Sequential string? If yes, go to (5). - // (2) Anything but sequential or cons? If yes, go to (6). - // (3) Cons string. If the string is flat, replace subject with first string. - // Otherwise bailout. - // (4) Is subject external? If yes, go to (7). - // (5) Sequential string. Load regexp code according to encoding. + // (1) Sequential string? If yes, go to (4). + // (2) Sequential or cons? If not, go to (5). + // (3) Cons string. If the string is flat, replace subject with first string + // and go to (1). Otherwise bail out to runtime. + // (4) Sequential string. Load regexp code according to encoding. // (E) Carry on. /// [...] // Deferred code at the end of the stub: - // (6) Not a long external string? If yes, go to (8). - // (7) External string. Make it, offset-wise, look like a sequential string. - // Go to (5). - // (8) Short external string or not a string? If yes, bail out to runtime. - // (9) Sliced string. Replace subject with parent. Go to (4). - - Label check_underlying; // (4) - Label seq_string; // (5) - Label not_seq_nor_cons; // (6) - Label external_string; // (7) - Label not_long_external; // (8) - - // (1) Sequential string? If yes, go to (5). + // (5) Long external string? If not, go to (7). + // (6) External string. Make it, offset-wise, look like a sequential string. + // Go to (4). + // (7) Short external string or not a string? If yes, bail out to runtime. + // (8) Sliced string. Replace subject with parent. Go to (1). + + Label check_underlying; // (1) + Label seq_string; // (4) + Label not_seq_nor_cons; // (5) + Label external_string; // (6) + Label not_long_external; // (7) + + __ 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, a0, Operand(kIsNotStringMask | kStringRepresentationMask | kShortExternalStringMask)); 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(kSlicedStringTag > kExternalStringTag); STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); - // Go to (6). + // Go to (5). __ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag)); // (3) Cons string. Check that it's flat. @@ -1730,19 +1739,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ LoadRoot(a1, Heap::kempty_stringRootIndex); __ Branch(&runtime, ne, a0, Operand(a1)); __ ld(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); + __ jmp(&check_underlying); - // (4) Is subject external? If yes, go to (7). - __ 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. + // (4) Sequential string. Load regexp code according to encoding. __ bind(&seq_string); // subject: sequential subject string (or look-alike, external string) // a3: original subject string @@ -1985,12 +1984,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kRegExpExec); // 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); - // Go to (8). + // Go to (7). __ 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); __ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); @@ -2010,20 +2009,20 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ Dsubu(subject, subject, 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); STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask)); __ 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. __ ld(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); __ SmiUntag(t0); __ ld(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); - __ jmp(&check_underlying); // Go to (4). + __ jmp(&check_underlying); // Go to (1). #endif // V8_INTERPRETED_REGEXP } diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index 1abc7ebf076e9d..e00478a6afaf01 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -1353,6 +1353,10 @@ int HeapNumber::get_sign() { 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) \ if (this->Is##Type()) { \ if (!that->Is##Type()) return false; \ diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 67a59638318844..f577d5e4d3ec4d 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -13715,7 +13715,9 @@ void JSFunction::CalculateInstanceSizeForDerivedClass( for (PrototypeIterator iter(isolate, this, PrototypeIterator::START_AT_RECEIVER); !iter.IsAtEnd(); iter.Advance()) { - JSFunction* func = iter.GetCurrent(); + JSReceiver* current = iter.GetCurrent(); + if (!current->IsJSFunction()) break; + JSFunction* func = JSFunction::cast(current); SharedFunctionInfo* shared = func->shared(); expected_nof_properties += shared->expected_nof_properties(); if (!IsSubclassConstructor(shared->kind())) { @@ -17347,6 +17349,16 @@ void HashTable::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::Put(Handle 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. table = EnsureCapacity(table, 1, key); table->AddEntry(table->FindInsertionEntry(hash), *key, *value); diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index a3d6a7288252f3..61c6e5ebe1fab6 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -9292,9 +9292,6 @@ class ExternalString: public String { static const int kResourceDataOffset = kResourceOffset + 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). inline bool is_short(); diff --git a/deps/v8/src/ppc/code-stubs-ppc.cc b/deps/v8/src/ppc/code-stubs-ppc.cc index f6befb269a8722..03c73af50357fb 100644 --- a/deps/v8/src/ppc/code-stubs-ppc.cc +++ b/deps/v8/src/ppc/code-stubs-ppc.cc @@ -698,11 +698,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { __ bind(&slow); - __ Push(lhs, rhs); - // Figure out which native to call and setup the arguments. 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 { + __ Push(lhs, rhs); int ncr; // NaN compare result if (cc == lt || cc == le) { ncr = GREATER; @@ -1633,48 +1641,49 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ LoadP(subject, MemOperand(sp, kSubjectOffset)); __ JumpIfSmi(subject, &runtime); __ 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 // r6: subject string - // r3: subject string instance type // regexp_data: RegExp data (FixedArray) // Handle subject string according to its encoding and representation: - // (1) Sequential string? If yes, go to (5). - // (2) Anything but sequential or cons? If yes, go to (6). - // (3) Cons string. If the string is flat, replace subject with first string. - // Otherwise bailout. - // (4) Is subject external? If yes, go to (7). - // (5) Sequential string. Load regexp code according to encoding. + // (1) Sequential string? If yes, go to (4). + // (2) Sequential or cons? If not, go to (5). + // (3) Cons string. If the string is flat, replace subject with first string + // and go to (1). Otherwise bail out to runtime. + // (4) Sequential string. Load regexp code according to encoding. // (E) Carry on. /// [...] // Deferred code at the end of the stub: - // (6) Not a long external string? If yes, go to (8). - // (7) External string. Make it, offset-wise, look like a sequential string. - // Go to (5). - // (8) Short external string or not a string? If yes, bail out to runtime. - // (9) Sliced string. Replace subject with parent. Go to (4). + // (5) Long external string? If not, go to (7). + // (6) External string. Make it, offset-wise, look like a sequential string. + // Go to (4). + // (7) Short external string or not a string? If yes, bail out to runtime. + // (8) Sliced string. Replace subject with parent. Go to (1). + + Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */, + not_seq_nor_cons /* 5 */, not_long_external /* 7 */; - Label seq_string /* 5 */, external_string /* 7 */, check_underlying /* 4 */, - not_seq_nor_cons /* 6 */, not_long_external /* 8 */; + __ 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 | kShortExternalStringMask) == 0x93); __ andi(r4, r3, Operand(kIsNotStringMask | kStringRepresentationMask | kShortExternalStringMask)); 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(kSlicedStringTag > kExternalStringTag); STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); STATIC_ASSERT(kExternalStringTag < 0xffffu); __ 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. // Replace subject with first string and reload instance type. @@ -1682,20 +1691,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ CompareRoot(r3, Heap::kempty_stringRootIndex); __ bne(&runtime); __ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); + __ b(&check_underlying); - // (4) Is subject external? If yes, go to (7). - __ 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. + // (4) Sequential string. Load regexp code according to encoding. __ bind(&seq_string); // subject: sequential subject string (or look-alike, external string) // r6: original subject string @@ -1928,12 +1926,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kRegExpExec); // 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); // 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); __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset)); __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset)); @@ -1950,15 +1948,15 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); __ subi(subject, subject, 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); STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0); __ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask)); __ 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. __ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset)); __ SmiUntag(r11); diff --git a/deps/v8/src/runtime/runtime-interpreter.cc b/deps/v8/src/runtime/runtime-interpreter.cc index cbacb554add809..7150a8b2873a73 100644 --- a/deps/v8/src/runtime/runtime-interpreter.cc +++ b/deps/v8/src/runtime/runtime-interpreter.cc @@ -16,109 +16,6 @@ namespace v8 { 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 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 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 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 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 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 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) { SealHandleScope shs(isolate); DCHECK_EQ(1, args.length()); diff --git a/deps/v8/src/runtime/runtime-object.cc b/deps/v8/src/runtime/runtime-object.cc index 415920d6c6755f..45a49925bd248e 100644 --- a/deps/v8/src/runtime/runtime-object.cc +++ b/deps/v8/src/runtime/runtime-object.cc @@ -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 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) { SealHandleScope scope(isolate); DCHECK_EQ(2, args.length()); diff --git a/deps/v8/src/runtime/runtime-operators.cc b/deps/v8/src/runtime/runtime-operators.cc index 02fd0cd33281b6..e55ab7c5423040 100644 --- a/deps/v8/src/runtime/runtime-operators.cc +++ b/deps/v8/src/runtime/runtime-operators.cc @@ -140,5 +140,81 @@ RUNTIME_FUNCTION(Runtime_BitwiseXor) { 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 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 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 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 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 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 result = Object::GreaterThanOrEqual(x, y); + if (!result.IsJust()) return isolate->heap()->exception(); + return isolate->heap()->ToBoolean(result.FromJust()); +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime.h b/deps/v8/src/runtime/runtime.h index 3b97bb2b369424..7019c3bf041907 100644 --- a/deps/v8/src/runtime/runtime.h +++ b/deps/v8/src/runtime/runtime.h @@ -206,14 +206,6 @@ namespace internal { F(ForInStep, 1, 1) #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(InterpreterLogicalNot, 1, 1) \ F(InterpreterTypeOf, 1, 1) \ @@ -461,8 +453,6 @@ namespace internal { F(ToLength, 1, 1) \ F(ToString, 1, 1) \ F(ToName, 1, 1) \ - F(Equals, 2, 1) \ - F(StrictEquals, 2, 1) \ F(SameValue, 2, 1) \ F(SameValueZero, 2, 1) \ F(Compare, 3, 1) \ @@ -497,7 +487,15 @@ namespace internal { F(ShiftRightLogical, 2, 1) \ F(BitwiseAnd, 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) \ F(IsJSProxy, 1, 1) \ diff --git a/deps/v8/src/type-feedback-vector.cc b/deps/v8/src/type-feedback-vector.cc index 9e60fcffa76855..4519bd65c2c2d7 100644 --- a/deps/v8/src/type-feedback-vector.cc +++ b/deps/v8/src/type-feedback-vector.cc @@ -340,6 +340,10 @@ void FeedbackNexus::ConfigurePremonomorphic() { 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(); SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate), SKIP_WRITE_BARRIER); @@ -347,6 +351,21 @@ void FeedbackNexus::ConfigureMegamorphic() { SKIP_WRITE_BARRIER); } +void KeyedLoadICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) { + Isolate* isolate = GetIsolate(); + SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate), + SKIP_WRITE_BARRIER); + SetFeedbackExtra(Smi::FromInt(static_cast(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(property_type)), + SKIP_WRITE_BARRIER); +} InlineCacheState LoadICNexus::StateFromFeedback() const { Isolate* isolate = GetIsolate(); @@ -824,10 +843,20 @@ KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const { return mode; } +IcCheckType KeyedLoadICNexus::GetKeyType() const { + Object* feedback = GetFeedback(); + if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) { + return static_cast(Smi::cast(GetFeedbackExtra())->value()); + } + return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT; +} IcCheckType KeyedStoreICNexus::GetKeyType() const { - // The structure of the vector slots tells us the type. - return GetFeedback()->IsName() ? PROPERTY : ELEMENT; + Object* feedback = GetFeedback(); + if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) { + return static_cast(Smi::cast(GetFeedbackExtra())->value()); + } + return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT; } } // namespace internal } // namespace v8 diff --git a/deps/v8/src/type-feedback-vector.h b/deps/v8/src/type-feedback-vector.h index d1c31a285fb656..effbfe7cc663ba 100644 --- a/deps/v8/src/type-feedback-vector.h +++ b/deps/v8/src/type-feedback-vector.h @@ -475,6 +475,9 @@ class KeyedLoadICNexus : public FeedbackNexus { void ConfigurePolymorphic(Handle name, MapHandleList* maps, CodeHandleList* handlers); + void ConfigureMegamorphicKeyed(IcCheckType property_type); + + IcCheckType GetKeyType() const; InlineCacheState StateFromFeedback() const override; Name* FindFirstName() const override; }; @@ -531,6 +534,7 @@ class KeyedStoreICNexus : public FeedbackNexus { void ConfigurePolymorphic(MapHandleList* maps, MapHandleList* transitioned_maps, CodeHandleList* handlers); + void ConfigureMegamorphicKeyed(IcCheckType property_type); KeyedAccessStoreMode GetKeyedAccessStoreMode() const; IcCheckType GetKeyType() const; diff --git a/deps/v8/src/type-info.cc b/deps/v8/src/type-info.cc index eca5eccda46bc6..ad253420bcd2fa 100644 --- a/deps/v8/src/type-info.cc +++ b/deps/v8/src/type-info.cc @@ -301,7 +301,7 @@ void TypeFeedbackOracle::KeyedPropertyReceiverTypes( KeyedLoadICNexus nexus(feedback_vector_, slot); CollectReceiverTypes(&nexus, receiver_types); *is_string = HasOnlyStringMaps(receiver_types); - *key_type = nexus.FindFirstName() != NULL ? PROPERTY : ELEMENT; + *key_type = nexus.GetKeyType(); } } diff --git a/deps/v8/src/x64/code-stubs-x64.cc b/deps/v8/src/x64/code-stubs-x64.cc index 4b3d02841b2834..f314b9cfcb6ece 100644 --- a/deps/v8/src/x64/code-stubs-x64.cc +++ b/deps/v8/src/x64/code-stubs-x64.cc @@ -667,35 +667,34 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); __ JumpIfSmi(rdi, &runtime); __ 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) // rdi: subject string // r15: subject string // Handle subject string according to its encoding and representation: // (1) Sequential two byte? If yes, go to (9). - // (2) Sequential one byte? If yes, go to (6). - // (3) Anything but sequential or cons? If yes, go to (7). - // (4) Cons string. If the string is flat, replace subject with first string. - // Otherwise bailout. - // (5a) Is subject sequential two byte? If yes, go to (9). - // (5b) Is subject external? If yes, go to (8). - // (6) One byte sequential. Load regexp code for one byte. + // (2) Sequential one byte? If yes, go to (5). + // (3) Sequential or cons? If not, go to (6). + // (4) Cons string. If the string is flat, replace subject with first string + // and go to (1). Otherwise bail out to runtime. + // (5) One byte sequential. Load regexp code for one byte. // (E) Carry on. /// [...] // Deferred code at the end of the stub: - // (7) Not a long external string? If yes, go to (10). - // (8) External string. Make it, offset-wise, look like a sequential string. - // (8a) Is the external string one byte? If yes, go to (6). - // (9) Two byte sequential. Load regexp code for one byte. Go to (E). + // (6) Long external string? If not, go to (10). + // (7) External string. Make it, offset-wise, look like a sequential string. + // (8) Is the external string one byte? If yes, go to (5). + // (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. - // (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 /* 5 */, seq_two_byte_string /* 9 */, + external_string /* 7 */, check_underlying /* 1 */, + not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */; - Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, - external_string /* 8 */, check_underlying /* 5a */, - not_seq_nor_cons /* 7 */, check_code /* E */, - 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). __ andb(rbx, Immediate(kIsNotStringMask | @@ -705,14 +704,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); __ 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. __ andb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask | 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 // have already been covered. STATIC_ASSERT(kConsStringTag < kExternalStringTag); @@ -720,7 +719,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); STATIC_ASSERT(kShortExternalStringTag > 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. // Replace subject with first string and reload instance type. @@ -728,22 +727,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { Heap::kempty_stringRootIndex); __ j(not_equal, &runtime); __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); - __ bind(&check_underlying); - __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); - __ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); + __ jmp(&check_underlying); - // (5a) Is subject sequential two byte? If yes, go to (9). - __ 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. + // (5) One byte sequential. Load regexp code for one byte. __ bind(&seq_one_byte_string); // rax: RegExp data (FixedArray) __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset)); @@ -990,12 +976,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kRegExpExec); // 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); // Compare flags are still set from (3). __ 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); __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); @@ -1010,13 +996,13 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 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)); - __ 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) // 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); __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); __ Set(rcx, 0); // Type is two byte. @@ -1029,7 +1015,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); __ 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. __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); @@ -1320,16 +1306,23 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { } __ 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) { - __ 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 { + // Push arguments below the return address to prepare jump to builtin. + __ PopReturnAddressTo(rcx); + __ Push(rdx); + __ Push(rax); __ Push(Smi::FromInt(NegativeComparisonResult(cc))); __ PushReturnAddressFrom(rcx); __ TailCallRuntime(Runtime::kCompare); diff --git a/deps/v8/src/x87/code-stubs-x87.cc b/deps/v8/src/x87/code-stubs-x87.cc index e1ad6a7f5af1ee..ff6c8d29e51e50 100644 --- a/deps/v8/src/x87/code-stubs-x87.cc +++ b/deps/v8/src/x87/code-stubs-x87.cc @@ -500,39 +500,37 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ mov(eax, Operand(esp, kSubjectOffset)); __ JumpIfSmi(eax, &runtime); __ 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 // edx: subject string - // ebx: subject string instance type // ecx: RegExp data (FixedArray) // Handle subject string according to its encoding and representation: // (1) Sequential two byte? If yes, go to (9). - // (2) Sequential one byte? If yes, go to (6). - // (3) Anything but sequential or cons? If yes, go to (7). - // (4) Cons string. If the string is flat, replace subject with first string. - // Otherwise bailout. - // (5a) Is subject sequential two byte? If yes, go to (9). - // (5b) Is subject external? If yes, go to (8). - // (6) One byte sequential. Load regexp code for one byte. + // (2) Sequential one byte? If yes, go to (5). + // (3) Sequential or cons? If not, go to (6). + // (4) Cons string. If the string is flat, replace subject with first string + // and go to (1). Otherwise bail out to runtime. + // (5) One byte sequential. Load regexp code for one byte. // (E) Carry on. /// [...] // Deferred code at the end of the stub: - // (7) Not a long external string? If yes, go to (10). - // (8) External string. Make it, offset-wise, look like a sequential string. - // (8a) Is the external string one byte? If yes, go to (6). - // (9) Two byte sequential. Load regexp code for one byte. Go to (E). + // (6) Long external string? If not, go to (10). + // (7) External string. Make it, offset-wise, look like a sequential string. + // (8) Is the external string one byte? If yes, go to (5). + // (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. - // (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 */, - external_string /* 8 */, check_underlying /* 5a */, - not_seq_nor_cons /* 7 */, check_code /* E */, - not_long_external /* 10 */; + Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */, + external_string /* 7 */, check_underlying /* 1 */, + not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */; + __ bind(&check_underlying); // (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 | kStringRepresentationMask | kStringEncodingMask | @@ -540,14 +538,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); __ 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. __ and_(ebx, Immediate(kIsNotStringMask | kStringRepresentationMask | 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 // have already been covered. STATIC_ASSERT(kConsStringTag < kExternalStringTag); @@ -555,32 +553,19 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); STATIC_ASSERT(kShortExternalStringTag > 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. // Replace subject with first string and reload instance type. __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string()); __ j(not_equal, &runtime); __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); - __ bind(&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). + __ jmp(&check_underlying); // eax: sequential subject string (or look-alike, external string) // edx: original subject string // 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); // 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 @@ -801,12 +786,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kRegExpExec); // 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); // Compare flags are still set from (3). __ 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); // Reload instance type. __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); @@ -822,14 +807,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 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); - __ 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) // edx: original subject string // 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); // 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 @@ -849,11 +834,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag)); __ 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. __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset)); __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset)); - __ jmp(&check_underlying); // Go to (5a). + __ jmp(&check_underlying); // Go to (1). #endif // V8_INTERPRETED_REGEXP } @@ -1150,21 +1135,26 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { } __ 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) { - __ 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 { + // Push arguments below the return address. + __ pop(ecx); + __ push(edx); + __ push(eax); __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); // Restore return address on the stack. __ push(ecx); - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) // tagged as a small integer. __ TailCallRuntime(Runtime::kCompare); diff --git a/deps/v8/src/zone.cc b/deps/v8/src/zone.cc index 9dcebba2dc1fc8..1f722f2f608952 100644 --- a/deps/v8/src/zone.cc +++ b/deps/v8/src/zone.cc @@ -105,7 +105,10 @@ void* Zone::New(size_t size) { Address result = position_; const size_t size_with_redzone = size + kASanRedzoneBytes; - if (limit_ < position_ + size_with_redzone) { + const uintptr_t limit = reinterpret_cast(limit_); + const uintptr_t position = reinterpret_cast(position_); + // position_ > limit_ can be true after the alignment correction above. + if (limit < position || size_with_redzone > limit - position) { result = NewExpand(size_with_redzone); } else { 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 // there isn't enough room in the Zone to satisfy the request. DCHECK_EQ(size, RoundDown(size, kAlignment)); - DCHECK_LT(limit_, position_ + size); + DCHECK(limit_ < position_ || + reinterpret_cast(limit_) - + reinterpret_cast(position_) < + size); // Compute the new segment size. We use a 'high water mark' // strategy, where we increase the segment size every time we expand diff --git a/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc index 14ec12f21b87f9..22321c36643e09 100644 --- a/deps/v8/test/cctest/test-regexp.cc +++ b/deps/v8/test/cctest/test-regexp.cc @@ -1967,3 +1967,26 @@ TEST(UseCountRegExp) { CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]); 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 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 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"); +} diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status index 2058dfaeaee46c..fc9c7174b145e6 100644 --- a/deps/v8/test/mjsunit/mjsunit.status +++ b/deps/v8/test/mjsunit/mjsunit.status @@ -862,7 +862,6 @@ 'array-literal-feedback': [FAIL], 'undetectable-compare': [FAIL], 'debug-liveedit-2': [FAIL], - 'compiler/deopt-tonumber-compare': [FAIL], 'es6/string-search': [FAIL], 'es6/mirror-collections': [FAIL], 'es6/regress/regress-468661': [FAIL], diff --git a/deps/v8/test/mjsunit/regress/regress-4788-1.js b/deps/v8/test/mjsunit/regress/regress-4788-1.js new file mode 100644 index 00000000000000..347ab5e59299b3 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-4788-1.js @@ -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))); diff --git a/deps/v8/test/mjsunit/regress/regress-4788-2.js b/deps/v8/test/mjsunit/regress/regress-4788-2.js new file mode 100644 index 00000000000000..5441705d546c9d --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-4788-2.js @@ -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))); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-594183.js b/deps/v8/test/mjsunit/regress/regress-crbug-594183.js new file mode 100644 index 00000000000000..c87e32545828e4 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-594183.js @@ -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); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-605581.js b/deps/v8/test/mjsunit/regress/regress-crbug-605581.js new file mode 100644 index 00000000000000..0f1daabead95a6 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-605581.js @@ -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); diff --git a/deps/v8/test/mjsunit/regress/regress-v8-4972.js b/deps/v8/test/mjsunit/regress/regress-v8-4972.js new file mode 100644 index 00000000000000..689ae039ba3b0e --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-v8-4972.js @@ -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 {},{}) {} diff --git a/deps/v8/test/mjsunit/undetectable-compare.js b/deps/v8/test/mjsunit/undetectable-compare.js index fbfbbe1051323d..3b97f5ee94dff7 100644 --- a/deps/v8/test/mjsunit/undetectable-compare.js +++ b/deps/v8/test/mjsunit/undetectable-compare.js @@ -92,5 +92,4 @@ for (var i = 0; i < 5; i++) { } -assertFalse(undetectable == %GetUndetectable()); assertFalse(undetectable === %GetUndetectable()); diff --git a/deps/v8/test/unittests/runtime/runtime-interpreter-unittest.cc b/deps/v8/test/unittests/runtime/runtime-interpreter-unittest.cc index 97b7992af9fd75..c10ddcd3191374 100644 --- a/deps/v8/test/unittests/runtime/runtime-interpreter-unittest.cc +++ b/deps/v8/test/unittests/runtime/runtime-interpreter-unittest.cc @@ -23,12 +23,6 @@ class RuntimeInterpreterTest : public TestWithIsolateAndZone { bool TestOperatorWithObjects(RuntimeMethod method, Handle lhs, Handle 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 x = isolate()->factory()->NewNumberFromInt(lhs); - Handle y = isolate()->factory()->NewNumberFromInt(rhs); - return TestOperatorWithObjects(method, x, y, expected); -} - - -bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, double lhs, - double rhs, bool expected) { - Handle x = isolate()->factory()->NewNumber(lhs); - Handle 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 x = isolate()->factory()->NewStringFromAsciiChecked(lhs); - Handle 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::min(), - std::numeric_limits::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) { double quiet_nan = std::numeric_limits::quiet_NaN(); std::pair, bool> cases[] = { diff --git a/deps/v8/tools/gen-postmortem-metadata.py b/deps/v8/tools/gen-postmortem-metadata.py index 15eafedfce390b..d808a2f2d6cd1c 100644 --- a/deps/v8/tools/gen-postmortem-metadata.py +++ b/deps/v8/tools/gen-postmortem-metadata.py @@ -92,6 +92,8 @@ 'value': 'DescriptorArray::kFirstIndex' }, { 'name': 'prop_type_field', 'value': 'DATA' }, + { 'name': 'prop_type_const_field', + 'value': 'DATA_CONSTANT' }, { 'name': 'prop_type_mask', 'value': 'PropertyDetails::TypeField::kMask' }, { 'name': 'prop_index_mask',