Browse Source

deps: upgrade to V8 5.0.71.47

Pick up the latest set of patch level updates from the V8 5.0 branch.
https://github.com/v8/v8/compare/5.0.71.35...5.0.71.47

PR-URL: https://github.com/nodejs/node/pull/6572
Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: JungMinu - Minwoo Jung <jmwsoft@gmail.com>
v6.x
Ali Ijaz Sheikh 9 years ago
committed by Evan Lucas
parent
commit
a6ca5e559a
  1. 2
      deps/v8/include/v8-version.h
  2. 81
      deps/v8/src/arm/code-stubs-arm.cc
  3. 94
      deps/v8/src/arm64/code-stubs-arm64.cc
  4. 3
      deps/v8/src/compiler/ia32/instruction-selector-ia32.cc
  5. 118
      deps/v8/src/compiler/js-generic-lowering.cc
  6. 1
      deps/v8/src/compiler/js-generic-lowering.h
  7. 7
      deps/v8/src/compiler/x64/instruction-selector-x64.cc
  8. 1
      deps/v8/src/debug/debug-evaluate.cc
  9. 100
      deps/v8/src/ia32/code-stubs-ia32.cc
  10. 30
      deps/v8/src/ic/ic.cc
  11. 20
      deps/v8/src/ic/ic.h
  12. 16
      deps/v8/src/interpreter/interpreter.cc
  13. 2
      deps/v8/src/isolate.cc
  14. 85
      deps/v8/src/mips/code-stubs-mips.cc
  15. 97
      deps/v8/src/mips64/code-stubs-mips64.cc
  16. 4
      deps/v8/src/objects-inl.h
  17. 20
      deps/v8/src/objects.cc
  18. 3
      deps/v8/src/objects.h
  19. 82
      deps/v8/src/ppc/code-stubs-ppc.cc
  20. 103
      deps/v8/src/runtime/runtime-interpreter.cc
  21. 22
      deps/v8/src/runtime/runtime-object.cc
  22. 76
      deps/v8/src/runtime/runtime-operators.cc
  23. 20
      deps/v8/src/runtime/runtime.h
  24. 33
      deps/v8/src/type-feedback-vector.cc
  25. 4
      deps/v8/src/type-feedback-vector.h
  26. 2
      deps/v8/src/type-info.cc
  27. 95
      deps/v8/src/x64/code-stubs-x64.cc
  28. 98
      deps/v8/src/x87/code-stubs-x87.cc
  29. 10
      deps/v8/src/zone.cc
  30. 23
      deps/v8/test/cctest/test-regexp.cc
  31. 1
      deps/v8/test/mjsunit/mjsunit.status
  32. 25
      deps/v8/test/mjsunit/regress/regress-4788-1.js
  33. 25
      deps/v8/test/mjsunit/regress/regress-4788-2.js
  34. 82
      deps/v8/test/mjsunit/regress/regress-crbug-594183.js
  35. 28
      deps/v8/test/mjsunit/regress/regress-crbug-605581.js
  36. 5
      deps/v8/test/mjsunit/regress/regress-v8-4972.js
  37. 1
      deps/v8/test/mjsunit/undetectable-compare.js
  38. 99
      deps/v8/test/unittests/runtime/runtime-interpreter-unittest.cc
  39. 2
      deps/v8/tools/gen-postmortem-metadata.py

2
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.)

81
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, &not_seq_nor_cons); // Go to (6).
__ b(ge, &not_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(&not_seq_nor_cons);
// Compare flags are still set.
__ b(gt, &not_long_external); // Go to (8).
__ b(gt, &not_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(&not_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);

94
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, &not_seq_nor_cons); // Go to (6).
__ B(ge, &not_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(&not_seq_nor_cons);
// Compare flags are still set.
__ B(ne, &not_long_external); // Go to (8).
__ B(ne, &not_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(&not_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
}

3
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,

118
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<int>(inputs.size()), &inputs.front());
// Decide how the return value from the above CompareIC can be converted into
// a JavaScript boolean oddball depending on the given token.
Node* false_value = jsgraph()->FalseConstant();
Node* true_value = jsgraph()->TrueConstant();
const Operator* op = nullptr;
switch (token) {
case Token::EQ: // a == 0
case Token::EQ_STRICT:
op = machine()->WordEqual();
break;
case Token::NE: // a != 0 becomes !(a == 0)
case Token::NE_STRICT:
op = machine()->WordEqual();
std::swap(true_value, false_value);
break;
case Token::LT: // a < 0
op = machine()->IntLessThan();
break;
case Token::GT: // a > 0 becomes !(a <= 0)
op = machine()->IntLessThanOrEqual();
std::swap(true_value, false_value);
break;
case Token::LTE: // a <= 0
op = machine()->IntLessThanOrEqual();
break;
case Token::GTE: // a >= 0 becomes !(a < 0)
op = machine()->IntLessThan();
std::swap(true_value, false_value);
break;
default:
UNREACHABLE();
}
Node* booleanize = graph()->NewNode(op, compare, jsgraph()->ZeroConstant());
// Finally patch the original node to select a boolean.
NodeProperties::ReplaceUses(node, node, compare, compare, compare);
node->TrimInputCount(3);
node->ReplaceInput(0, booleanize);
node->ReplaceInput(1, true_value);
node->ReplaceInput(2, false_value);
NodeProperties::ChangeOp(node,
common()->Select(MachineRepresentation::kTagged));
}
#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));

1
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);

7
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

1
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();
}
}

100
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, &not_seq_nor_cons); // Go to (7).
__ j(greater_equal, &not_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(&not_seq_nor_cons);
// Compare flags are still set from (3).
__ j(greater, &not_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);

30
deps/v8/src/ic/ic.cc

@ -573,13 +573,21 @@ static bool MigrateDeprecated(Handle<Object> object) {
return true;
}
void IC::ConfigureVectorState(IC::State new_state) {
void IC::ConfigureVectorState(IC::State new_state, Handle<Object> 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<KeyedLoadICNexus>();
nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
} else {
DCHECK(kind() == Code::KEYED_STORE_IC);
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
}
} else {
UNREACHABLE();
}
@ -662,7 +670,7 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> 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> name, Handle<Code> 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<Object>());
TRACE_IC("LoadIC", lookup->name());
return;
}
@ -1378,7 +1386,7 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> 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<Object> StoreIC::Store(Handle<Object> object, Handle<Name> 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<Object> 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<Object>());
TRACE_IC("StoreIC", lookup->name());
return;
}
@ -2072,7 +2080,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> 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<Object> KeyedStoreIC::Store(Handle<Object> 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");
}

20
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<Object> key);
// Configure the vector for MONOMORPHIC.
void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Handle<Code> 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<IcCheckType, LoadICState::kNextBitFieldOffset, 1> {};
static ExtraICState ComputeExtraICState(TypeofMode typeof_mode,
IcCheckType key_type) {
return LoadICState(typeof_mode).GetExtraICState() |
IcCheckTypeField::encode(key_type);
}
static IcCheckType GetKeyType(ExtraICState extra_state) {
return IcCheckTypeField::decode(extra_state);
}
KeyedLoadIC(FrameDepth depth, Isolate* isolate,
KeyedLoadICNexus* nexus = NULL)
: LoadIC(depth, isolate, nexus) {

16
deps/v8/src/interpreter/interpreter.cc

@ -1139,7 +1139,7 @@ void Interpreter::DoNewWide(InterpreterAssembler* assembler) {
//
// Test if the value in the <src> 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 <src> 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 <src> 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 <src> 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 <src> 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 <src> 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 <src> 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 <src> register is greater than or equal to the
// accumulator.
void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kInterpreterGreaterThanOrEqual, assembler);
DoBinaryOp(Runtime::kGreaterThanOrEqual, assembler);
}

2
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(

85
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(&not_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(&not_seq_nor_cons);
// Go to (8).
// Go to (7).
__ Branch(&not_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(&not_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);

97
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(&not_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(&not_seq_nor_cons);
// Go to (8).
// Go to (7).
__ Branch(&not_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(&not_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
}

4
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; \

20
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<JSFunction>();
JSReceiver* current = iter.GetCurrent<JSReceiver>();
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<Derived, Shape, Key>::Rehash(Key key) {
}
}
}
// Wipe deleted entries.
Heap* heap = GetHeap();
Object* the_hole = heap->the_hole_value();
Object* undefined = heap->undefined_value();
for (uint32_t current = 0; current < capacity; current++) {
if (get(EntryToIndex(current)) == the_hole) {
set(EntryToIndex(current), undefined);
}
}
SetNumberOfDeletedElements(0);
}
@ -18707,6 +18719,12 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
return table;
}
// 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);

3
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();

82
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(&not_seq_nor_cons); // Go to (6).
__ bge(&not_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(&not_seq_nor_cons);
// Compare flags are still set.
__ bgt(&not_long_external); // Go to (8).
__ bgt(&not_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(&not_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);

103
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<bool> result = Object::Equals(x, y);
if (result.IsJust()) {
return isolate->heap()->ToBoolean(result.FromJust());
} else {
return isolate->heap()->exception();
}
}
RUNTIME_FUNCTION(Runtime_InterpreterNotEquals) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::Equals(x, y);
if (result.IsJust()) {
return isolate->heap()->ToBoolean(!result.FromJust());
} else {
return isolate->heap()->exception();
}
}
RUNTIME_FUNCTION(Runtime_InterpreterLessThan) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::LessThan(x, y);
if (result.IsJust()) {
return isolate->heap()->ToBoolean(result.FromJust());
} else {
return isolate->heap()->exception();
}
}
RUNTIME_FUNCTION(Runtime_InterpreterGreaterThan) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::GreaterThan(x, y);
if (result.IsJust()) {
return isolate->heap()->ToBoolean(result.FromJust());
} else {
return isolate->heap()->exception();
}
}
RUNTIME_FUNCTION(Runtime_InterpreterLessThanOrEqual) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::LessThanOrEqual(x, y);
if (result.IsJust()) {
return isolate->heap()->ToBoolean(result.FromJust());
} else {
return isolate->heap()->exception();
}
}
RUNTIME_FUNCTION(Runtime_InterpreterGreaterThanOrEqual) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::GreaterThanOrEqual(x, y);
if (result.IsJust()) {
return isolate->heap()->ToBoolean(result.FromJust());
} else {
return isolate->heap()->exception();
}
}
RUNTIME_FUNCTION(Runtime_InterpreterStrictEquals) {
SealHandleScope shs(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
return isolate->heap()->ToBoolean(x->StrictEquals(y));
}
RUNTIME_FUNCTION(Runtime_InterpreterStrictNotEquals) {
SealHandleScope shs(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
return isolate->heap()->ToBoolean(!x->StrictEquals(y));
}
RUNTIME_FUNCTION(Runtime_InterpreterToBoolean) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());

22
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<bool> result = Object::Equals(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
// TODO(bmeurer): Change this at some point to return true/false instead.
return Smi::FromInt(result.FromJust() ? EQUAL : NOT_EQUAL);
}
RUNTIME_FUNCTION(Runtime_StrictEquals) {
SealHandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
// TODO(bmeurer): Change this at some point to return true/false instead.
return Smi::FromInt(x->StrictEquals(y) ? EQUAL : NOT_EQUAL);
}
RUNTIME_FUNCTION(Runtime_SameValue) {
SealHandleScope scope(isolate);
DCHECK_EQ(2, args.length());

76
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<bool> result = Object::Equals(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(result.FromJust());
}
RUNTIME_FUNCTION(Runtime_NotEqual) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::Equals(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(!result.FromJust());
}
RUNTIME_FUNCTION(Runtime_StrictEqual) {
SealHandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
return isolate->heap()->ToBoolean(x->StrictEquals(y));
}
RUNTIME_FUNCTION(Runtime_StrictNotEqual) {
SealHandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
return isolate->heap()->ToBoolean(!x->StrictEquals(y));
}
RUNTIME_FUNCTION(Runtime_LessThan) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::LessThan(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(result.FromJust());
}
RUNTIME_FUNCTION(Runtime_GreaterThan) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::GreaterThan(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(result.FromJust());
}
RUNTIME_FUNCTION(Runtime_LessThanOrEqual) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::LessThanOrEqual(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(result.FromJust());
}
RUNTIME_FUNCTION(Runtime_GreaterThanOrEqual) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::GreaterThanOrEqual(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(result.FromJust());
}
} // namespace internal
} // namespace v8

20
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) \

33
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<int>(property_type)),
SKIP_WRITE_BARRIER);
}
void KeyedStoreICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) {
Isolate* isolate = GetIsolate();
SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
SKIP_WRITE_BARRIER);
SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
SKIP_WRITE_BARRIER);
}
InlineCacheState LoadICNexus::StateFromFeedback() const {
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<IcCheckType>(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<IcCheckType>(Smi::cast(GetFeedbackExtra())->value());
}
return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
}
} // namespace internal
} // namespace v8

4
deps/v8/src/type-feedback-vector.h

@ -475,6 +475,9 @@ class KeyedLoadICNexus : public FeedbackNexus {
void ConfigurePolymorphic(Handle<Name> 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;

2
deps/v8/src/type-info.cc

@ -301,7 +301,7 @@ void TypeFeedbackOracle::KeyedPropertyReceiverTypes(
KeyedLoadICNexus nexus(feedback_vector_, slot);
CollectReceiverTypes<FeedbackNexus>(&nexus, receiver_types);
*is_string = HasOnlyStringMaps(receiver_types);
*key_type = nexus.FindFirstName() != NULL ? PROPERTY : ELEMENT;
*key_type = nexus.GetKeyType();
}
}

95
deps/v8/src/x64/code-stubs-x64.cc

@ -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, &not_seq_nor_cons); // Go to (7).
__ j(greater_equal, &not_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(&not_seq_nor_cons);
// Compare flags are still set from (3).
__ j(greater, &not_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);

98
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, &not_seq_nor_cons); // Go to (7).
__ j(greater_equal, &not_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(&not_seq_nor_cons);
// Compare flags are still set from (3).
__ j(greater, &not_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);

10
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<uintptr_t>(limit_);
const uintptr_t position = reinterpret_cast<uintptr_t>(position_);
// position_ > limit_ can be true after the alignment correction above.
if (limit < position || size_with_redzone > limit - position) {
result = NewExpand(size_with_redzone);
} 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<uintptr_t>(limit_) -
reinterpret_cast<uintptr_t>(position_) <
size);
// Compute the new segment size. We use a 'high water mark'
// strategy, where we increase the segment size every time we expand

23
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<v8::String> external =
v8::String::NewExternalOneByte(isolate, new UncachedExternalString())
.ToLocalChecked();
CHECK(v8::Utils::OpenHandle(*external)->map() ==
CcTest::i_isolate()->heap()->short_external_one_byte_string_map());
v8::Local<v8::Object> global = env->Global();
global->Set(env.local(), v8_str("external"), external).FromJust();
CompileRun("var re = /y(.)/; re.test('ab');");
ExpectString("external.substring(1).match(re)[1]", "z");
}

1
deps/v8/test/mjsunit/mjsunit.status

@ -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],

25
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)));

25
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)));

82
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);

28
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);

5
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 {},{}) {}

1
deps/v8/test/mjsunit/undetectable-compare.js

@ -92,5 +92,4 @@ for (var i = 0; i < 5; i++) {
}
assertFalse(undetectable == %GetUndetectable());
assertFalse(undetectable === %GetUndetectable());

99
deps/v8/test/unittests/runtime/runtime-interpreter-unittest.cc

@ -23,12 +23,6 @@ class RuntimeInterpreterTest : public TestWithIsolateAndZone {
bool TestOperatorWithObjects(RuntimeMethod method, Handle<Object> lhs,
Handle<Object> rhs, bool expected);
bool TestOperator(RuntimeMethod method, int32_t lhs, int32_t rhs,
bool expected);
bool TestOperator(RuntimeMethod method, double lhs, double rhs,
bool expected);
bool TestOperator(RuntimeMethod method, const char* lhs, const char* rhs,
bool expected);
};
@ -44,99 +38,6 @@ bool RuntimeInterpreterTest::TestOperatorWithObjects(RuntimeMethod method,
}
bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, int32_t lhs,
int32_t rhs, bool expected) {
Handle<Object> x = isolate()->factory()->NewNumberFromInt(lhs);
Handle<Object> y = isolate()->factory()->NewNumberFromInt(rhs);
return TestOperatorWithObjects(method, x, y, expected);
}
bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, double lhs,
double rhs, bool expected) {
Handle<Object> x = isolate()->factory()->NewNumber(lhs);
Handle<Object> y = isolate()->factory()->NewNumber(rhs);
CHECK_EQ(HeapNumber::cast(*x)->value(), lhs);
CHECK_EQ(HeapNumber::cast(*y)->value(), rhs);
return TestOperatorWithObjects(method, x, y, expected);
}
bool RuntimeInterpreterTest::TestOperator(RuntimeMethod method, const char* lhs,
const char* rhs, bool expected) {
Handle<Object> x = isolate()->factory()->NewStringFromAsciiChecked(lhs);
Handle<Object> y = isolate()->factory()->NewStringFromAsciiChecked(rhs);
return TestOperatorWithObjects(method, x, y, expected);
}
TEST_F(RuntimeInterpreterTest, TestOperatorsWithIntegers) {
int32_t inputs[] = {kMinInt, Smi::kMinValue, -17, -1, 0, 1,
991, Smi::kMaxValue, kMaxInt};
TRACED_FOREACH(int, lhs, inputs) {
TRACED_FOREACH(int, rhs, inputs) {
#define INTEGER_OPERATOR_CHECK(r, op, x, y) \
CHECK(TestOperator(Runtime_Interpreter##r, x, y, x op y))
INTEGER_OPERATOR_CHECK(Equals, ==, lhs, rhs);
INTEGER_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
INTEGER_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
INTEGER_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
INTEGER_OPERATOR_CHECK(LessThan, <, lhs, rhs);
INTEGER_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
INTEGER_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
INTEGER_OPERATOR_CHECK(GreaterThanOrEqual, >=, lhs, rhs);
#undef INTEGER_OPERATOR_CHECK
}
}
}
TEST_F(RuntimeInterpreterTest, TestOperatorsWithDoubles) {
double inputs[] = {std::numeric_limits<double>::min(),
std::numeric_limits<double>::max(),
-0.001,
0.01,
3.14,
-6.02214086e23};
TRACED_FOREACH(double, lhs, inputs) {
TRACED_FOREACH(double, rhs, inputs) {
#define DOUBLE_OPERATOR_CHECK(r, op, x, y) \
CHECK(TestOperator(Runtime_Interpreter##r, x, y, x op y))
DOUBLE_OPERATOR_CHECK(Equals, ==, lhs, rhs);
DOUBLE_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
DOUBLE_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
DOUBLE_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
DOUBLE_OPERATOR_CHECK(LessThan, <, lhs, rhs);
DOUBLE_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
DOUBLE_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
DOUBLE_OPERATOR_CHECK(GreaterThanOrEqual, >=, lhs, rhs);
#undef DOUBLE_OPERATOR_CHECK
}
}
}
TEST_F(RuntimeInterpreterTest, TestOperatorsWithString) {
const char* inputs[] = {"abc", "a", "def", "0"};
TRACED_FOREACH(const char*, lhs, inputs) {
TRACED_FOREACH(const char*, rhs, inputs) {
#define STRING_OPERATOR_CHECK(r, op, x, y) \
CHECK(TestOperator(Runtime_Interpreter##r, x, y, \
std::string(x) op std::string(y)))
STRING_OPERATOR_CHECK(Equals, ==, lhs, rhs);
STRING_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
STRING_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
STRING_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
STRING_OPERATOR_CHECK(LessThan, <, lhs, rhs);
STRING_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
STRING_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
STRING_OPERATOR_CHECK(GreaterThanOrEqual, >=, lhs, rhs);
#undef STRING_OPERATOR_CHECK
}
}
}
TEST_F(RuntimeInterpreterTest, ToBoolean) {
double quiet_nan = std::numeric_limits<double>::quiet_NaN();
std::pair<Handle<Object>, bool> cases[] = {

2
deps/v8/tools/gen-postmortem-metadata.py

@ -92,6 +92,8 @@ consts_misc = [
'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',

Loading…
Cancel
Save