deps: upgrade to V8 5.0.71.47
Pick up the latest set of patch level updates from the V8 5.0 branch. https://github.com/v8/v8/compare/5.0.71.35...5.0.71.47 PR-URL: https://github.com/nodejs/node/pull/6572 Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: JungMinu - Minwoo Jung <jmwsoft@gmail.com>
This commit is contained in:
parent
fe4837afcc
commit
e16e611089
2
deps/v8/include/v8-version.h
vendored
2
deps/v8/include/v8-version.h
vendored
@ -11,7 +11,7 @@
|
||||
#define V8_MAJOR_VERSION 5
|
||||
#define V8_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
vendored
81
deps/v8/src/arm/code-stubs-arm.cc
vendored
@ -671,11 +671,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
__ bind(&slow);
|
||||
|
||||
__ Push(lhs, rhs);
|
||||
// Figure out which native to call and setup the arguments.
|
||||
if (cc == eq) {
|
||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
||||
{
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||
__ Push(lhs, rhs);
|
||||
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||
}
|
||||
// Turn true into 0 and false into some non-zero value.
|
||||
STATIC_ASSERT(EQUAL == 0);
|
||||
__ LoadRoot(r1, Heap::kTrueValueRootIndex);
|
||||
__ sub(r0, r0, r1);
|
||||
__ Ret();
|
||||
} else {
|
||||
__ Push(lhs, rhs);
|
||||
int ncr; // NaN compare result
|
||||
if (cc == lt || cc == le) {
|
||||
ncr = GREATER;
|
||||
@ -1573,34 +1581,33 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ ldr(subject, MemOperand(sp, kSubjectOffset));
|
||||
__ JumpIfSmi(subject, &runtime);
|
||||
__ mov(r3, subject); // Make a copy of the original subject string.
|
||||
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
||||
// subject: subject string
|
||||
// r3: subject string
|
||||
// r0: subject string instance type
|
||||
// regexp_data: RegExp data (FixedArray)
|
||||
// Handle subject string according to its encoding and representation:
|
||||
// (1) Sequential string? If yes, go to (5).
|
||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
||||
// (3) Cons string. If the string is flat, replace subject with first string.
|
||||
// Otherwise bailout.
|
||||
// (4) Is subject external? If yes, go to (7).
|
||||
// (5) Sequential string. Load regexp code according to encoding.
|
||||
// (1) Sequential string? If yes, go to (4).
|
||||
// (2) Sequential or cons? If not, go to (5).
|
||||
// (3) Cons string. If the string is flat, replace subject with first string
|
||||
// and go to (1). Otherwise bail out to runtime.
|
||||
// (4) Sequential string. Load regexp code according to encoding.
|
||||
// (E) Carry on.
|
||||
/// [...]
|
||||
|
||||
// Deferred code at the end of the stub:
|
||||
// (6) Not a long external string? If yes, go to (8).
|
||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||
// Go to (5).
|
||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
||||
// (5) Long external string? If not, go to (7).
|
||||
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||
// Go to (4).
|
||||
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||
// (8) Sliced string. Replace subject with parent. Go to (1).
|
||||
|
||||
Label seq_string /* 5 */, external_string /* 7 */,
|
||||
check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
|
||||
not_long_external /* 8 */;
|
||||
Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
|
||||
not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
|
||||
|
||||
// (1) Sequential string? If yes, go to (5).
|
||||
__ bind(&check_underlying);
|
||||
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
||||
|
||||
// (1) Sequential string? If yes, go to (4).
|
||||
__ and_(r1,
|
||||
r0,
|
||||
Operand(kIsNotStringMask |
|
||||
@ -1608,15 +1615,15 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
kShortExternalStringMask),
|
||||
SetCC);
|
||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||
__ b(eq, &seq_string); // Go to (5).
|
||||
__ b(eq, &seq_string); // Go to (4).
|
||||
|
||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
||||
// (2) Sequential or cons? If not, go to (5).
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||
__ cmp(r1, Operand(kExternalStringTag));
|
||||
__ b(ge, ¬_seq_nor_cons); // Go to (6).
|
||||
__ b(ge, ¬_seq_nor_cons); // Go to (5).
|
||||
|
||||
// (3) Cons string. Check that it's flat.
|
||||
// Replace subject with first string and reload instance type.
|
||||
@ -1624,19 +1631,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ CompareRoot(r0, Heap::kempty_stringRootIndex);
|
||||
__ b(ne, &runtime);
|
||||
__ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||
__ jmp(&check_underlying);
|
||||
|
||||
// (4) Is subject external? If yes, go to (7).
|
||||
__ bind(&check_underlying);
|
||||
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ tst(r0, Operand(kStringRepresentationMask));
|
||||
// The underlying external string is never a short external string.
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
||||
__ b(ne, &external_string); // Go to (7).
|
||||
|
||||
// (5) Sequential string. Load regexp code according to encoding.
|
||||
// (4) Sequential string. Load regexp code according to encoding.
|
||||
__ bind(&seq_string);
|
||||
// subject: sequential subject string (or look-alike, external string)
|
||||
// r3: original subject string
|
||||
@ -1869,12 +1866,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||
|
||||
// Deferred code for string handling.
|
||||
// (6) Not a long external string? If yes, go to (8).
|
||||
// (5) Long external string? If not, go to (7).
|
||||
__ bind(¬_seq_nor_cons);
|
||||
// Compare flags are still set.
|
||||
__ b(gt, ¬_long_external); // Go to (8).
|
||||
__ b(gt, ¬_long_external); // Go to (7).
|
||||
|
||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||
__ bind(&external_string);
|
||||
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
||||
@ -1891,15 +1888,15 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ sub(subject,
|
||||
subject,
|
||||
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
__ jmp(&seq_string); // Go to (5).
|
||||
__ jmp(&seq_string); // Go to (4).
|
||||
|
||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
||||
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||
__ bind(¬_long_external);
|
||||
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
|
||||
__ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask));
|
||||
__ b(ne, &runtime);
|
||||
|
||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
||||
// (8) Sliced string. Replace subject with parent. Go to (4).
|
||||
// Load offset into r9 and replace subject string with parent.
|
||||
__ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||
__ SmiUntag(r9);
|
||||
|
90
deps/v8/src/arm64/code-stubs-arm64.cc
vendored
90
deps/v8/src/arm64/code-stubs-arm64.cc
vendored
@ -628,11 +628,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
__ Bind(&slow);
|
||||
|
||||
__ 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).
|
||||
// (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; // (4)
|
||||
Label seq_string; // (5)
|
||||
Label not_seq_nor_cons; // (6)
|
||||
Label external_string; // (7)
|
||||
Label not_long_external; // (8)
|
||||
Label check_underlying; // (1)
|
||||
Label seq_string; // (4)
|
||||
Label not_seq_nor_cons; // (5)
|
||||
Label external_string; // (6)
|
||||
Label not_long_external; // (7)
|
||||
|
||||
// (1) Sequential string? If yes, go to (5).
|
||||
__ Bind(&check_underlying);
|
||||
__ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
|
||||
|
||||
// (1) Sequential string? If yes, go to (4).
|
||||
__ And(string_representation,
|
||||
string_type,
|
||||
kIsNotStringMask |
|
||||
@ -1784,36 +1792,24 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// is a String
|
||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||
STATIC_ASSERT(kShortExternalStringTag != 0);
|
||||
__ Cbz(string_representation, &seq_string); // Go to (5).
|
||||
__ Cbz(string_representation, &seq_string); // Go to (4).
|
||||
|
||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
||||
// (2) Sequential or cons? If not, go to (5).
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||
__ Cmp(string_representation, kExternalStringTag);
|
||||
__ B(ge, ¬_seq_nor_cons); // Go to (6).
|
||||
__ B(ge, ¬_seq_nor_cons); // Go to (5).
|
||||
|
||||
// (3) Cons string. Check that it's flat.
|
||||
__ Ldr(x10, FieldMemOperand(subject, ConsString::kSecondOffset));
|
||||
__ JumpIfNotRoot(x10, Heap::kempty_stringRootIndex, &runtime);
|
||||
// Replace subject with first string.
|
||||
__ Ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||
__ B(&check_underlying);
|
||||
|
||||
// (4) Is subject external? If yes, go to (7).
|
||||
__ Bind(&check_underlying);
|
||||
// Reload the string type.
|
||||
__ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
// The underlying external string is never a short external string.
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
||||
__ TestAndBranchIfAnySet(string_type.X(),
|
||||
kStringRepresentationMask,
|
||||
&external_string); // Go to (7).
|
||||
|
||||
// (5) Sequential string. Load regexp code according to encoding.
|
||||
// (4) Sequential string. Load regexp code according to encoding.
|
||||
__ Bind(&seq_string);
|
||||
|
||||
// Check that the third argument is a positive smi less than the subject
|
||||
@ -2083,12 +2079,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||
|
||||
// Deferred code for string handling.
|
||||
// (6) Not a long external string? If yes, go to (8).
|
||||
// (5) Long external string? If not, go to (7).
|
||||
__ Bind(¬_seq_nor_cons);
|
||||
// Compare flags are still set.
|
||||
__ B(ne, ¬_long_external); // Go to (8).
|
||||
__ B(ne, ¬_long_external); // Go to (7).
|
||||
|
||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||
__ Bind(&external_string);
|
||||
if (masm->emit_debug_code()) {
|
||||
// Assert that we do not have a cons or slice (indirect strings) here.
|
||||
@ -2106,9 +2102,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// Move the pointer so that offset-wise, it looks like a sequential string.
|
||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||
__ Sub(subject, subject, SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
||||
__ B(&seq_string); // Go to (5).
|
||||
__ B(&seq_string); // Go to (4).
|
||||
|
||||
// (8) If this is a short external string or not a string, bail out to
|
||||
// (7) If this is a short external string or not a string, bail out to
|
||||
// runtime.
|
||||
__ Bind(¬_long_external);
|
||||
STATIC_ASSERT(kShortExternalStringTag != 0);
|
||||
@ -2116,11 +2112,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
kShortExternalStringMask | kIsNotStringMask,
|
||||
&runtime);
|
||||
|
||||
// (9) Sliced string. Replace subject with parent.
|
||||
// (8) Sliced string. Replace subject with parent.
|
||||
__ Ldr(sliced_string_offset,
|
||||
UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||
__ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
|
||||
__ B(&check_underlying); // Go to (4).
|
||||
__ B(&check_underlying); // Go to (1).
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -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
vendored
118
deps/v8/src/compiler/js-generic-lowering.cc
vendored
@ -81,117 +81,22 @@ REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV)
|
||||
REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
|
||||
#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
vendored
1
deps/v8/src/compiler/js-generic-lowering.h
vendored
@ -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);
|
||||
|
||||
|
@ -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
vendored
1
deps/v8/src/debug/debug-evaluate.cc
vendored
@ -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
vendored
100
deps/v8/src/ia32/code-stubs-ia32.cc
vendored
@ -798,39 +798,37 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ mov(eax, Operand(esp, kSubjectOffset));
|
||||
__ JumpIfSmi(eax, &runtime);
|
||||
__ mov(edx, eax); // Make a copy of the original subject string.
|
||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
||||
|
||||
// eax: subject string
|
||||
// edx: subject string
|
||||
// ebx: subject string instance type
|
||||
// ecx: RegExp data (FixedArray)
|
||||
// Handle subject string according to its encoding and representation:
|
||||
// (1) Sequential two byte? If yes, go to (9).
|
||||
// (2) Sequential one byte? If yes, go to (6).
|
||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
||||
// (4) Cons string. If the string is flat, replace subject with first string.
|
||||
// Otherwise bailout.
|
||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
||||
// (5b) Is subject external? If yes, go to (8).
|
||||
// (6) One byte sequential. Load regexp code for one byte.
|
||||
// (2) Sequential one byte? If yes, go to (5).
|
||||
// (3) Sequential or cons? If not, go to (6).
|
||||
// (4) Cons string. If the string is flat, replace subject with first string
|
||||
// and go to (1). Otherwise bail out to runtime.
|
||||
// (5) One byte sequential. Load regexp code for one byte.
|
||||
// (E) Carry on.
|
||||
/// [...]
|
||||
|
||||
// Deferred code at the end of the stub:
|
||||
// (7) Not a long external string? If yes, go to (10).
|
||||
// (8) External string. Make it, offset-wise, look like a sequential string.
|
||||
// (8a) Is the external string one byte? If yes, go to (6).
|
||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
||||
// (6) Long external string? If not, go to (10).
|
||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||
// (8) Is the external string one byte? If yes, go to (5).
|
||||
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||
// (10) Short external string or not a string? If yes, bail out to runtime.
|
||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
||||
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||
|
||||
Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
|
||||
external_string /* 8 */, check_underlying /* 5a */,
|
||||
not_seq_nor_cons /* 7 */, check_code /* E */,
|
||||
not_long_external /* 10 */;
|
||||
Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
|
||||
external_string /* 7 */, check_underlying /* 1 */,
|
||||
not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
|
||||
|
||||
__ bind(&check_underlying);
|
||||
// (1) Sequential two byte? If yes, go to (9).
|
||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
||||
|
||||
__ and_(ebx, kIsNotStringMask |
|
||||
kStringRepresentationMask |
|
||||
kStringEncodingMask |
|
||||
@ -838,14 +836,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
||||
|
||||
// (2) Sequential one byte? If yes, go to (6).
|
||||
// (2) Sequential one byte? If yes, go to (5).
|
||||
// Any other sequential string must be one byte.
|
||||
__ and_(ebx, Immediate(kIsNotStringMask |
|
||||
kStringRepresentationMask |
|
||||
kShortExternalStringMask));
|
||||
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6).
|
||||
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
|
||||
|
||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
||||
// (3) Sequential or cons? If not, go to (6).
|
||||
// We check whether the subject string is a cons, since sequential strings
|
||||
// have already been covered.
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
@ -853,32 +851,19 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||
__ cmp(ebx, Immediate(kExternalStringTag));
|
||||
__ j(greater_equal, ¬_seq_nor_cons); // Go to (7).
|
||||
__ j(greater_equal, ¬_seq_nor_cons); // Go to (6).
|
||||
|
||||
// (4) Cons string. Check that it's flat.
|
||||
// Replace subject with first string and reload instance type.
|
||||
__ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
|
||||
__ j(not_equal, &runtime);
|
||||
__ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
|
||||
__ bind(&check_underlying);
|
||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
__ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
||||
|
||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
||||
__ test_b(ebx, kStringRepresentationMask | kStringEncodingMask);
|
||||
STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
|
||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
||||
// (5b) Is subject external? If yes, go to (8).
|
||||
__ test_b(ebx, kStringRepresentationMask);
|
||||
// The underlying external string is never a short external string.
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
||||
__ j(not_zero, &external_string); // Go to (8).
|
||||
__ jmp(&check_underlying);
|
||||
|
||||
// eax: sequential subject string (or look-alike, external string)
|
||||
// edx: original subject string
|
||||
// ecx: RegExp data (FixedArray)
|
||||
// (6) One byte sequential. Load regexp code for one byte.
|
||||
// (5) One byte sequential. Load regexp code for one byte.
|
||||
__ bind(&seq_one_byte_string);
|
||||
// Load previous index and check range before edx is overwritten. We have
|
||||
// to use edx instead of eax here because it might have been only made to
|
||||
@ -1105,12 +1090,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||
|
||||
// Deferred code for string handling.
|
||||
// (7) Not a long external string? If yes, go to (10).
|
||||
// (6) Long external string? If not, go to (10).
|
||||
__ bind(¬_seq_nor_cons);
|
||||
// Compare flags are still set from (3).
|
||||
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
|
||||
|
||||
// (8) External string. Short external strings have been ruled out.
|
||||
// (7) External string. Short external strings have been ruled out.
|
||||
__ bind(&external_string);
|
||||
// Reload instance type.
|
||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
@ -1126,14 +1111,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||
__ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||
// (8a) Is the external string one byte? If yes, go to (6).
|
||||
// (8) Is the external string one byte? If yes, go to (5).
|
||||
__ test_b(ebx, kStringEncodingMask);
|
||||
__ j(not_zero, &seq_one_byte_string); // Goto (6).
|
||||
__ j(not_zero, &seq_one_byte_string); // Go to (5).
|
||||
|
||||
// eax: sequential subject string (or look-alike, external string)
|
||||
// edx: original subject string
|
||||
// ecx: RegExp data (FixedArray)
|
||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
||||
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||
__ bind(&seq_two_byte_string);
|
||||
// Load previous index and check range before edx is overwritten. We have
|
||||
// to use edx instead of eax here because it might have been only made to
|
||||
@ -1153,11 +1138,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
|
||||
__ j(not_zero, &runtime);
|
||||
|
||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
||||
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||
// Load offset into edi and replace subject string with parent.
|
||||
__ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
|
||||
__ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
|
||||
__ jmp(&check_underlying); // Go to (5a).
|
||||
__ jmp(&check_underlying); // Go to (1).
|
||||
#endif // V8_INTERPRETED_REGEXP
|
||||
}
|
||||
|
||||
@ -1442,21 +1427,24 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
}
|
||||
__ bind(&runtime_call);
|
||||
|
||||
// Push arguments below the return address.
|
||||
__ pop(ecx);
|
||||
__ push(edx);
|
||||
__ push(eax);
|
||||
|
||||
// Figure out which native to call and setup the arguments.
|
||||
if (cc == equal) {
|
||||
__ push(ecx);
|
||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
__ Push(edx);
|
||||
__ Push(eax);
|
||||
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||
}
|
||||
// Turn true into 0 and false into some non-zero value.
|
||||
STATIC_ASSERT(EQUAL == 0);
|
||||
__ sub(eax, Immediate(isolate()->factory()->true_value()));
|
||||
__ Ret();
|
||||
} else {
|
||||
// Push arguments below the return address.
|
||||
__ pop(ecx);
|
||||
__ push(edx);
|
||||
__ push(eax);
|
||||
__ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
|
||||
|
||||
// Restore return address on the stack.
|
||||
__ push(ecx);
|
||||
|
||||
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
|
||||
// tagged as a small integer.
|
||||
__ TailCallRuntime(Runtime::kCompare);
|
||||
|
30
deps/v8/src/ic/ic.cc
vendored
30
deps/v8/src/ic/ic.cc
vendored
@ -573,13 +573,21 @@ static bool MigrateDeprecated(Handle<Object> object) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
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
vendored
20
deps/v8/src/ic/ic.h
vendored
@ -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
vendored
16
deps/v8/src/interpreter/interpreter.cc
vendored
@ -1139,7 +1139,7 @@ void Interpreter::DoNewWide(InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Test if the value in the <src> register equals the accumulator.
|
||||
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
vendored
2
deps/v8/src/isolate.cc
vendored
@ -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
vendored
85
deps/v8/src/mips/code-stubs-mips.cc
vendored
@ -718,13 +718,21 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
// Never falls through to here.
|
||||
|
||||
__ 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 /* 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);
|
||||
__ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
||||
|
||||
// (1) Sequential string? If yes, go to (4).
|
||||
__ And(a1,
|
||||
a0,
|
||||
Operand(kIsNotStringMask |
|
||||
@ -1719,12 +1724,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||
__ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5).
|
||||
|
||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
||||
// (2) Sequential or cons? If not, go to (5).
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||
// Go to (6).
|
||||
// Go to (5).
|
||||
__ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
|
||||
|
||||
// (3) Cons string. Check that it's flat.
|
||||
@ -1733,19 +1738,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ LoadRoot(a1, Heap::kempty_stringRootIndex);
|
||||
__ Branch(&runtime, ne, a0, Operand(a1));
|
||||
__ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||
__ jmp(&check_underlying);
|
||||
|
||||
// (4) Is subject external? If yes, go to (7).
|
||||
__ bind(&check_underlying);
|
||||
__ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ And(at, a0, Operand(kStringRepresentationMask));
|
||||
// The underlying external string is never a short external string.
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
||||
__ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7).
|
||||
|
||||
// (5) Sequential string. Load regexp code according to encoding.
|
||||
// (4) Sequential string. Load regexp code according to encoding.
|
||||
__ bind(&seq_string);
|
||||
// subject: sequential subject string (or look-alike, external string)
|
||||
// a3: original subject string
|
||||
@ -1987,12 +1982,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||
|
||||
// Deferred code for string handling.
|
||||
// (6) Not a long external string? If yes, go to (8).
|
||||
// (5) Long external string? If not, go to (7).
|
||||
__ bind(¬_seq_nor_cons);
|
||||
// Go to (8).
|
||||
// Go to (7).
|
||||
__ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag));
|
||||
|
||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||
__ bind(&external_string);
|
||||
__ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
||||
@ -2014,13 +2009,13 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
||||
__ jmp(&seq_string); // Go to (5).
|
||||
|
||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
||||
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||
__ bind(¬_long_external);
|
||||
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
|
||||
__ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
|
||||
__ Branch(&runtime, ne, at, Operand(zero_reg));
|
||||
|
||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
||||
// (8) Sliced string. Replace subject with parent. Go to (4).
|
||||
// Load offset into t0 and replace subject string with parent.
|
||||
__ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||
__ sra(t0, t0, kSmiTagSize);
|
||||
|
93
deps/v8/src/mips64/code-stubs-mips64.cc
vendored
93
deps/v8/src/mips64/code-stubs-mips64.cc
vendored
@ -715,13 +715,21 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
// Never falls through to here.
|
||||
|
||||
__ 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).
|
||||
// (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; // (4)
|
||||
Label seq_string; // (5)
|
||||
Label not_seq_nor_cons; // (6)
|
||||
Label external_string; // (7)
|
||||
Label not_long_external; // (8)
|
||||
Label check_underlying; // (1)
|
||||
Label seq_string; // (4)
|
||||
Label not_seq_nor_cons; // (5)
|
||||
Label external_string; // (6)
|
||||
Label not_long_external; // (7)
|
||||
|
||||
// (1) Sequential string? If yes, go to (5).
|
||||
__ bind(&check_underlying);
|
||||
__ ld(a2, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ lbu(a0, FieldMemOperand(a2, Map::kInstanceTypeOffset));
|
||||
|
||||
// (1) Sequential string? If yes, go to (4).
|
||||
__ And(a1,
|
||||
a0,
|
||||
Operand(kIsNotStringMask |
|
||||
kStringRepresentationMask |
|
||||
kShortExternalStringMask));
|
||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||
__ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5).
|
||||
__ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (4).
|
||||
|
||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
||||
// (2) Sequential or cons? If not, go to (5).
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||
// Go to (6).
|
||||
// Go to (5).
|
||||
__ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
|
||||
|
||||
// (3) Cons string. Check that it's flat.
|
||||
@ -1730,19 +1739,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ LoadRoot(a1, Heap::kempty_stringRootIndex);
|
||||
__ Branch(&runtime, ne, a0, Operand(a1));
|
||||
__ ld(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||
__ jmp(&check_underlying);
|
||||
|
||||
// (4) Is subject external? If yes, go to (7).
|
||||
__ bind(&check_underlying);
|
||||
__ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ And(at, a0, Operand(kStringRepresentationMask));
|
||||
// The underlying external string is never a short external string.
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
||||
__ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7).
|
||||
|
||||
// (5) Sequential string. Load regexp code according to encoding.
|
||||
// (4) Sequential string. Load regexp code according to encoding.
|
||||
__ bind(&seq_string);
|
||||
// subject: sequential subject string (or look-alike, external string)
|
||||
// a3: original subject string
|
||||
@ -1985,12 +1984,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||
|
||||
// Deferred code for string handling.
|
||||
// (6) Not a long external string? If yes, go to (8).
|
||||
// (5) Long external string? If not, go to (7).
|
||||
__ bind(¬_seq_nor_cons);
|
||||
// Go to (8).
|
||||
// Go to (7).
|
||||
__ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag));
|
||||
|
||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||
__ bind(&external_string);
|
||||
__ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
||||
@ -2010,20 +2009,20 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ Dsubu(subject,
|
||||
subject,
|
||||
SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
||||
__ jmp(&seq_string); // Go to (5).
|
||||
__ jmp(&seq_string); // Go to (4).
|
||||
|
||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
||||
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||
__ bind(¬_long_external);
|
||||
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
|
||||
__ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
|
||||
__ Branch(&runtime, ne, at, Operand(zero_reg));
|
||||
|
||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
||||
// (8) Sliced string. Replace subject with parent. Go to (4).
|
||||
// Load offset into t0 and replace subject string with parent.
|
||||
__ ld(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||
__ SmiUntag(t0);
|
||||
__ ld(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
|
||||
__ jmp(&check_underlying); // Go to (4).
|
||||
__ jmp(&check_underlying); // Go to (1).
|
||||
#endif // V8_INTERPRETED_REGEXP
|
||||
}
|
||||
|
||||
|
4
deps/v8/src/objects-inl.h
vendored
4
deps/v8/src/objects-inl.h
vendored
@ -1353,6 +1353,10 @@ int HeapNumber::get_sign() {
|
||||
|
||||
|
||||
bool Simd128Value::Equals(Simd128Value* that) {
|
||||
// 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
vendored
20
deps/v8/src/objects.cc
vendored
@ -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
vendored
3
deps/v8/src/objects.h
vendored
@ -9292,9 +9292,6 @@ class ExternalString: public String {
|
||||
static const int kResourceDataOffset = kResourceOffset + kPointerSize;
|
||||
static const int 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
vendored
82
deps/v8/src/ppc/code-stubs-ppc.cc
vendored
@ -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 /* 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 */;
|
||||
|
||||
__ bind(&check_underlying);
|
||||
__ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
|
||||
|
||||
// (1) Sequential string? If yes, go to (4).
|
||||
|
||||
// (1) Sequential string? If yes, go to (5).
|
||||
STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask |
|
||||
kShortExternalStringMask) == 0x93);
|
||||
__ andi(r4, r3, Operand(kIsNotStringMask | kStringRepresentationMask |
|
||||
kShortExternalStringMask));
|
||||
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
|
||||
__ beq(&seq_string, cr0); // Go to (5).
|
||||
__ beq(&seq_string, cr0); // Go to (4).
|
||||
|
||||
// (2) Anything but sequential or cons? If yes, go to (6).
|
||||
// (2) Sequential or cons? If not, go to (5).
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||
STATIC_ASSERT(kExternalStringTag < 0xffffu);
|
||||
__ cmpi(r4, Operand(kExternalStringTag));
|
||||
__ bge(¬_seq_nor_cons); // Go to (6).
|
||||
__ bge(¬_seq_nor_cons); // Go to (5).
|
||||
|
||||
// (3) Cons string. Check that it's flat.
|
||||
// Replace subject with first string and reload instance type.
|
||||
@ -1682,20 +1691,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ CompareRoot(r3, Heap::kempty_stringRootIndex);
|
||||
__ bne(&runtime);
|
||||
__ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||
__ b(&check_underlying);
|
||||
|
||||
// (4) Is subject external? If yes, go to (7).
|
||||
__ bind(&check_underlying);
|
||||
__ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
STATIC_ASSERT(kStringRepresentationMask == 3);
|
||||
__ andi(r0, r3, Operand(kStringRepresentationMask));
|
||||
// The underlying external string is never a short external string.
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
||||
__ bne(&external_string, cr0); // Go to (7).
|
||||
|
||||
// (5) Sequential string. Load regexp code according to encoding.
|
||||
// (4) Sequential string. Load regexp code according to encoding.
|
||||
__ bind(&seq_string);
|
||||
// subject: sequential subject string (or look-alike, external string)
|
||||
// r6: original subject string
|
||||
@ -1928,12 +1926,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||
|
||||
// Deferred code for string handling.
|
||||
// (6) Not a long external string? If yes, go to (8).
|
||||
// (5) Long external string? If not, go to (7).
|
||||
__ bind(¬_seq_nor_cons);
|
||||
// Compare flags are still set.
|
||||
__ bgt(¬_long_external); // Go to (8).
|
||||
__ bgt(¬_long_external); // Go to (7).
|
||||
|
||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||
// (6) External string. Make it, offset-wise, look like a sequential string.
|
||||
__ bind(&external_string);
|
||||
__ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
|
||||
__ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
|
||||
@ -1950,15 +1948,15 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||
__ subi(subject, subject,
|
||||
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
__ b(&seq_string); // Go to (5).
|
||||
__ b(&seq_string); // Go to (4).
|
||||
|
||||
// (8) Short external string or not a string? If yes, bail out to runtime.
|
||||
// (7) Short external string or not a string? If yes, bail out to runtime.
|
||||
__ bind(¬_long_external);
|
||||
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0);
|
||||
__ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask));
|
||||
__ bne(&runtime, cr0);
|
||||
|
||||
// (9) Sliced string. Replace subject with parent. Go to (4).
|
||||
// (8) Sliced string. Replace subject with parent. Go to (4).
|
||||
// Load offset into r11 and replace subject string with parent.
|
||||
__ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset));
|
||||
__ SmiUntag(r11);
|
||||
|
103
deps/v8/src/runtime/runtime-interpreter.cc
vendored
103
deps/v8/src/runtime/runtime-interpreter.cc
vendored
@ -16,109 +16,6 @@
|
||||
namespace v8 {
|
||||
namespace 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
vendored
22
deps/v8/src/runtime/runtime-object.cc
vendored
@ -1073,28 +1073,6 @@ RUNTIME_FUNCTION(Runtime_ToName) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_Equals) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
|
||||
Maybe<bool> result = Object::Equals(x, y);
|
||||
if (!result.IsJust()) return isolate->heap()->exception();
|
||||
// TODO(bmeurer): Change this at some point to return true/false instead.
|
||||
return Smi::FromInt(result.FromJust() ? EQUAL : NOT_EQUAL);
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_StrictEquals) {
|
||||
SealHandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_CHECKED(Object, x, 0);
|
||||
CONVERT_ARG_CHECKED(Object, y, 1);
|
||||
// TODO(bmeurer): Change this at some point to return true/false instead.
|
||||
return Smi::FromInt(x->StrictEquals(y) ? EQUAL : NOT_EQUAL);
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_SameValue) {
|
||||
SealHandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
|
76
deps/v8/src/runtime/runtime-operators.cc
vendored
76
deps/v8/src/runtime/runtime-operators.cc
vendored
@ -140,5 +140,81 @@ RUNTIME_FUNCTION(Runtime_BitwiseXor) {
|
||||
return *result;
|
||||
}
|
||||
|
||||
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
vendored
20
deps/v8/src/runtime/runtime.h
vendored
@ -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
vendored
33
deps/v8/src/type-feedback-vector.cc
vendored
@ -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
vendored
4
deps/v8/src/type-feedback-vector.h
vendored
@ -475,6 +475,9 @@ class KeyedLoadICNexus : public FeedbackNexus {
|
||||
void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
|
||||
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
vendored
2
deps/v8/src/type-info.cc
vendored
@ -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
vendored
95
deps/v8/src/x64/code-stubs-x64.cc
vendored
@ -667,35 +667,34 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
|
||||
__ 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 /* 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);
|
||||
__ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
|
||||
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
|
||||
|
||||
// (1) Sequential two byte? If yes, go to (9).
|
||||
__ andb(rbx, Immediate(kIsNotStringMask |
|
||||
@ -705,14 +704,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
||||
|
||||
// (2) Sequential one byte? If yes, go to (6).
|
||||
// (2) Sequential one byte? If yes, go to (5).
|
||||
// Any other sequential string must be one byte.
|
||||
__ andb(rbx, Immediate(kIsNotStringMask |
|
||||
kStringRepresentationMask |
|
||||
kShortExternalStringMask));
|
||||
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6).
|
||||
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
|
||||
|
||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
||||
// (3) Sequential or cons? If not, go to (6).
|
||||
// We check whether the subject string is a cons, since sequential strings
|
||||
// have already been covered.
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
@ -720,7 +719,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||
__ cmpp(rbx, Immediate(kExternalStringTag));
|
||||
__ j(greater_equal, ¬_seq_nor_cons); // Go to (7).
|
||||
__ j(greater_equal, ¬_seq_nor_cons); // Go to (6).
|
||||
|
||||
// (4) Cons string. Check that it's flat.
|
||||
// Replace subject with first string and reload instance type.
|
||||
@ -728,22 +727,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
Heap::kempty_stringRootIndex);
|
||||
__ j(not_equal, &runtime);
|
||||
__ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
|
||||
__ bind(&check_underlying);
|
||||
__ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
|
||||
__ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
|
||||
__ jmp(&check_underlying);
|
||||
|
||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
||||
__ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask));
|
||||
STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
|
||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
||||
// (5b) Is subject external? If yes, go to (8).
|
||||
__ testb(rbx, Immediate(kStringRepresentationMask));
|
||||
// The underlying external string is never a short external string.
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
||||
__ j(not_zero, &external_string); // Go to (8)
|
||||
|
||||
// (6) One byte sequential. Load regexp code for one byte.
|
||||
// (5) One byte sequential. Load regexp code for one byte.
|
||||
__ bind(&seq_one_byte_string);
|
||||
// rax: RegExp data (FixedArray)
|
||||
__ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset));
|
||||
@ -990,12 +976,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||
|
||||
// Deferred code for string handling.
|
||||
// (7) Not a long external string? If yes, go to (10).
|
||||
// (6) Long external string? If not, go to (10).
|
||||
__ bind(¬_seq_nor_cons);
|
||||
// Compare flags are still set from (3).
|
||||
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
|
||||
|
||||
// (8) External string. Short external strings have been ruled out.
|
||||
// (7) External string. Short external strings have been ruled out.
|
||||
__ bind(&external_string);
|
||||
__ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
|
||||
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
|
||||
@ -1010,13 +996,13 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||
__ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||
// (8a) Is the external string one byte? If yes, go to (6).
|
||||
// (8) Is the external string one byte? If yes, go to (5).
|
||||
__ testb(rbx, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &seq_one_byte_string); // Goto (6).
|
||||
__ j(not_zero, &seq_one_byte_string); // Go to (5).
|
||||
|
||||
// rdi: subject string (flat two-byte)
|
||||
// rax: RegExp data (FixedArray)
|
||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
||||
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||
__ bind(&seq_two_byte_string);
|
||||
__ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
|
||||
__ Set(rcx, 0); // Type is two byte.
|
||||
@ -1029,7 +1015,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask));
|
||||
__ j(not_zero, &runtime);
|
||||
|
||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
||||
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||
// Load offset into r14 and replace subject string with parent.
|
||||
__ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset));
|
||||
__ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
|
||||
@ -1320,16 +1306,23 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
}
|
||||
__ bind(&runtime_call);
|
||||
|
||||
// Push arguments below the return address to prepare jump to builtin.
|
||||
__ PopReturnAddressTo(rcx);
|
||||
__ Push(rdx);
|
||||
__ Push(rax);
|
||||
|
||||
// Figure out which native to call and setup the arguments.
|
||||
if (cc == equal) {
|
||||
__ PushReturnAddressFrom(rcx);
|
||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
__ Push(rdx);
|
||||
__ Push(rax);
|
||||
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||
}
|
||||
// Turn true into 0 and false into some non-zero value.
|
||||
STATIC_ASSERT(EQUAL == 0);
|
||||
__ LoadRoot(rdx, Heap::kTrueValueRootIndex);
|
||||
__ subp(rax, rdx);
|
||||
__ Ret();
|
||||
} else {
|
||||
// Push arguments below the return address to prepare jump to builtin.
|
||||
__ PopReturnAddressTo(rcx);
|
||||
__ Push(rdx);
|
||||
__ Push(rax);
|
||||
__ Push(Smi::FromInt(NegativeComparisonResult(cc)));
|
||||
__ PushReturnAddressFrom(rcx);
|
||||
__ TailCallRuntime(Runtime::kCompare);
|
||||
|
98
deps/v8/src/x87/code-stubs-x87.cc
vendored
98
deps/v8/src/x87/code-stubs-x87.cc
vendored
@ -500,39 +500,37 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ mov(eax, Operand(esp, kSubjectOffset));
|
||||
__ JumpIfSmi(eax, &runtime);
|
||||
__ mov(edx, eax); // Make a copy of the original subject string.
|
||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
||||
|
||||
// eax: subject string
|
||||
// edx: subject string
|
||||
// ebx: subject string instance type
|
||||
// ecx: RegExp data (FixedArray)
|
||||
// Handle subject string according to its encoding and representation:
|
||||
// (1) Sequential two byte? If yes, go to (9).
|
||||
// (2) Sequential one byte? If yes, go to (6).
|
||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
||||
// (4) Cons string. If the string is flat, replace subject with first string.
|
||||
// Otherwise bailout.
|
||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
||||
// (5b) Is subject external? If yes, go to (8).
|
||||
// (6) One byte sequential. Load regexp code for one byte.
|
||||
// (2) Sequential one byte? If yes, go to (5).
|
||||
// (3) Sequential or cons? If not, go to (6).
|
||||
// (4) Cons string. If the string is flat, replace subject with first string
|
||||
// and go to (1). Otherwise bail out to runtime.
|
||||
// (5) One byte sequential. Load regexp code for one byte.
|
||||
// (E) Carry on.
|
||||
/// [...]
|
||||
|
||||
// Deferred code at the end of the stub:
|
||||
// (7) Not a long external string? If yes, go to (10).
|
||||
// (8) External string. Make it, offset-wise, look like a sequential string.
|
||||
// (8a) Is the external string one byte? If yes, go to (6).
|
||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
||||
// (6) Long external string? If not, go to (10).
|
||||
// (7) External string. Make it, offset-wise, look like a sequential string.
|
||||
// (8) Is the external string one byte? If yes, go to (5).
|
||||
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||
// (10) Short external string or not a string? If yes, bail out to runtime.
|
||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
||||
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||
|
||||
Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
|
||||
external_string /* 8 */, check_underlying /* 5a */,
|
||||
not_seq_nor_cons /* 7 */, check_code /* E */,
|
||||
not_long_external /* 10 */;
|
||||
Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
|
||||
external_string /* 7 */, check_underlying /* 1 */,
|
||||
not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
|
||||
|
||||
__ bind(&check_underlying);
|
||||
// (1) Sequential two byte? If yes, go to (9).
|
||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
||||
|
||||
__ and_(ebx, kIsNotStringMask |
|
||||
kStringRepresentationMask |
|
||||
kStringEncodingMask |
|
||||
@ -540,14 +538,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
|
||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
||||
|
||||
// (2) Sequential one byte? If yes, go to (6).
|
||||
// (2) Sequential one byte? If yes, go to (5).
|
||||
// Any other sequential string must be one byte.
|
||||
__ and_(ebx, Immediate(kIsNotStringMask |
|
||||
kStringRepresentationMask |
|
||||
kShortExternalStringMask));
|
||||
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6).
|
||||
__ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
|
||||
|
||||
// (3) Anything but sequential or cons? If yes, go to (7).
|
||||
// (3) Sequential or cons? If not, go to (6).
|
||||
// We check whether the subject string is a cons, since sequential strings
|
||||
// have already been covered.
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
@ -555,32 +553,19 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
|
||||
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
|
||||
__ cmp(ebx, Immediate(kExternalStringTag));
|
||||
__ j(greater_equal, ¬_seq_nor_cons); // Go to (7).
|
||||
__ j(greater_equal, ¬_seq_nor_cons); // Go to (6).
|
||||
|
||||
// (4) Cons string. Check that it's flat.
|
||||
// Replace subject with first string and reload instance type.
|
||||
__ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
|
||||
__ j(not_equal, &runtime);
|
||||
__ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
|
||||
__ bind(&check_underlying);
|
||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
__ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
||||
|
||||
// (5a) Is subject sequential two byte? If yes, go to (9).
|
||||
__ test_b(ebx, kStringRepresentationMask | kStringEncodingMask);
|
||||
STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
|
||||
__ j(zero, &seq_two_byte_string); // Go to (9).
|
||||
// (5b) Is subject external? If yes, go to (8).
|
||||
__ test_b(ebx, kStringRepresentationMask);
|
||||
// The underlying external string is never a short external string.
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
|
||||
STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
|
||||
__ j(not_zero, &external_string); // Go to (8).
|
||||
__ jmp(&check_underlying);
|
||||
|
||||
// eax: sequential subject string (or look-alike, external string)
|
||||
// edx: original subject string
|
||||
// ecx: RegExp data (FixedArray)
|
||||
// (6) One byte sequential. Load regexp code for one byte.
|
||||
// (5) One byte sequential. Load regexp code for one byte.
|
||||
__ bind(&seq_one_byte_string);
|
||||
// Load previous index and check range before edx is overwritten. We have
|
||||
// to use edx instead of eax here because it might have been only made to
|
||||
@ -801,12 +786,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||
|
||||
// Deferred code for string handling.
|
||||
// (7) Not a long external string? If yes, go to (10).
|
||||
// (6) Long external string? If not, go to (10).
|
||||
__ bind(¬_seq_nor_cons);
|
||||
// Compare flags are still set from (3).
|
||||
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
|
||||
|
||||
// (8) External string. Short external strings have been ruled out.
|
||||
// (7) External string. Short external strings have been ruled out.
|
||||
__ bind(&external_string);
|
||||
// Reload instance type.
|
||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
@ -822,14 +807,14 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
|
||||
__ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||
// (8a) Is the external string one byte? If yes, go to (6).
|
||||
// (8) Is the external string one byte? If yes, go to (5).
|
||||
__ test_b(ebx, kStringEncodingMask);
|
||||
__ j(not_zero, &seq_one_byte_string); // Goto (6).
|
||||
__ j(not_zero, &seq_one_byte_string); // Go to (5).
|
||||
|
||||
// eax: sequential subject string (or look-alike, external string)
|
||||
// edx: original subject string
|
||||
// ecx: RegExp data (FixedArray)
|
||||
// (9) Two byte sequential. Load regexp code for one byte. Go to (E).
|
||||
// (9) Two byte sequential. Load regexp code for two byte. Go to (E).
|
||||
__ bind(&seq_two_byte_string);
|
||||
// Load previous index and check range before edx is overwritten. We have
|
||||
// to use edx instead of eax here because it might have been only made to
|
||||
@ -849,11 +834,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
__ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
|
||||
__ j(not_zero, &runtime);
|
||||
|
||||
// (11) Sliced string. Replace subject with parent. Go to (5a).
|
||||
// (11) Sliced string. Replace subject with parent. Go to (1).
|
||||
// Load offset into edi and replace subject string with parent.
|
||||
__ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
|
||||
__ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
|
||||
__ jmp(&check_underlying); // Go to (5a).
|
||||
__ jmp(&check_underlying); // Go to (1).
|
||||
#endif // V8_INTERPRETED_REGEXP
|
||||
}
|
||||
|
||||
@ -1150,21 +1135,26 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
}
|
||||
__ bind(&runtime_call);
|
||||
|
||||
// Push arguments below the return address.
|
||||
__ pop(ecx);
|
||||
__ push(edx);
|
||||
__ push(eax);
|
||||
|
||||
// Figure out which native to call and setup the arguments.
|
||||
if (cc == equal) {
|
||||
__ push(ecx);
|
||||
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
__ Push(edx);
|
||||
__ Push(eax);
|
||||
__ CallRuntime(strict() ? Runtime::kStrictEqual : Runtime::kEqual);
|
||||
}
|
||||
// Turn true into 0 and false into some non-zero value.
|
||||
STATIC_ASSERT(EQUAL == 0);
|
||||
__ sub(eax, Immediate(isolate()->factory()->true_value()));
|
||||
__ Ret();
|
||||
} else {
|
||||
// Push arguments below the return address.
|
||||
__ pop(ecx);
|
||||
__ push(edx);
|
||||
__ push(eax);
|
||||
__ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
|
||||
|
||||
// Restore return address on the stack.
|
||||
__ push(ecx);
|
||||
|
||||
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
|
||||
// tagged as a small integer.
|
||||
__ TailCallRuntime(Runtime::kCompare);
|
||||
|
10
deps/v8/src/zone.cc
vendored
10
deps/v8/src/zone.cc
vendored
@ -105,7 +105,10 @@ void* Zone::New(size_t size) {
|
||||
Address result = position_;
|
||||
|
||||
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
vendored
23
deps/v8/test/cctest/test-regexp.cc
vendored
@ -1967,3 +1967,26 @@ TEST(UseCountRegExp) {
|
||||
CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]);
|
||||
CHECK(resultToStringError->IsObject());
|
||||
}
|
||||
|
||||
class UncachedExternalString
|
||||
: public v8::String::ExternalOneByteStringResource {
|
||||
public:
|
||||
const char* data() const override { return "abcdefghijklmnopqrstuvwxyz"; }
|
||||
size_t length() const override { return 26; }
|
||||
bool IsCompressible() const override { return true; }
|
||||
};
|
||||
|
||||
TEST(UncachedExternalString) {
|
||||
v8::Isolate* isolate = CcTest::isolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
LocalContext env;
|
||||
v8::Local<v8::String> external =
|
||||
v8::String::NewExternalOneByte(isolate, new UncachedExternalString())
|
||||
.ToLocalChecked();
|
||||
CHECK(v8::Utils::OpenHandle(*external)->map() ==
|
||||
CcTest::i_isolate()->heap()->short_external_one_byte_string_map());
|
||||
v8::Local<v8::Object> global = env->Global();
|
||||
global->Set(env.local(), v8_str("external"), external).FromJust();
|
||||
CompileRun("var re = /y(.)/; re.test('ab');");
|
||||
ExpectString("external.substring(1).match(re)[1]", "z");
|
||||
}
|
||||
|
1
deps/v8/test/mjsunit/mjsunit.status
vendored
1
deps/v8/test/mjsunit/mjsunit.status
vendored
@ -862,7 +862,6 @@
|
||||
'array-literal-feedback': [FAIL],
|
||||
'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
vendored
Normal file
25
deps/v8/test/mjsunit/regress/regress-4788-1.js
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
var f = (function() {
|
||||
"use asm";
|
||||
function foo(x) {
|
||||
return x == 0;
|
||||
}
|
||||
return foo;
|
||||
})();
|
||||
|
||||
function deopt(f) {
|
||||
return {
|
||||
toString : function() {
|
||||
%DeoptimizeFunction(f);
|
||||
return "2";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
assertFalse(f(deopt(f)));
|
25
deps/v8/test/mjsunit/regress/regress-4788-2.js
vendored
Normal file
25
deps/v8/test/mjsunit/regress/regress-4788-2.js
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
var f = (function() {
|
||||
"use asm";
|
||||
function foo(x) {
|
||||
return x < x;
|
||||
}
|
||||
return foo;
|
||||
})();
|
||||
|
||||
function deopt(f) {
|
||||
return {
|
||||
toString : function() {
|
||||
%DeoptimizeFunction(f);
|
||||
return "2";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
assertFalse(f(deopt(f)));
|
82
deps/v8/test/mjsunit/regress/regress-crbug-594183.js
vendored
Normal file
82
deps/v8/test/mjsunit/regress/regress-crbug-594183.js
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
var global = {}
|
||||
|
||||
var fish = [
|
||||
{'name': 'foo'},
|
||||
{'name': 'bar'},
|
||||
];
|
||||
|
||||
for (var i = 0; i < fish.length; i++) {
|
||||
global[fish[i].name] = 1;
|
||||
}
|
||||
|
||||
function load() {
|
||||
var sum = 0;
|
||||
for (var i = 0; i < fish.length; i++) {
|
||||
var name = fish[i].name;
|
||||
sum += global[name];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
load();
|
||||
load();
|
||||
%OptimizeFunctionOnNextCall(load);
|
||||
load();
|
||||
assertOptimized(load);
|
||||
|
||||
function store() {
|
||||
for (var i = 0; i < fish.length; i++) {
|
||||
var name = fish[i].name;
|
||||
global[name] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
store();
|
||||
store();
|
||||
%OptimizeFunctionOnNextCall(store);
|
||||
store();
|
||||
assertOptimized(store);
|
||||
|
||||
// Regression test for KeyedStoreIC bug: would use PROPERTY mode erroneously.
|
||||
|
||||
function store_element(obj, key) {
|
||||
obj[key] = 0;
|
||||
}
|
||||
|
||||
var o1 = new Array(3);
|
||||
var o2 = new Array(3);
|
||||
o2.o2 = "o2";
|
||||
var o3 = new Array(3);
|
||||
o3.o3 = "o3";
|
||||
var o4 = new Array(3);
|
||||
o4.o4 = "o4";
|
||||
var o5 = new Array(3);
|
||||
o5.o5 = "o5";
|
||||
// Make the KeyedStoreIC megamorphic.
|
||||
store_element(o1, 0); // Premonomorphic
|
||||
store_element(o1, 0); // Monomorphic
|
||||
store_element(o2, 0); // 2-way polymorphic.
|
||||
store_element(o3, 0); // 3-way polymorphic.
|
||||
store_element(o4, 0); // 4-way polymorphic.
|
||||
store_element(o5, 0); // Megamorphic.
|
||||
|
||||
function inferrable_store(key) {
|
||||
store_element(o5, key);
|
||||
}
|
||||
|
||||
inferrable_store(0);
|
||||
inferrable_store(0);
|
||||
%OptimizeFunctionOnNextCall(inferrable_store);
|
||||
inferrable_store(0);
|
||||
assertOptimized(inferrable_store);
|
||||
// If |inferrable_store| emitted a generic keyed store, it won't deopt upon
|
||||
// seeing a property name key. It should have inferred a receiver map and
|
||||
// emitted an elements store, however.
|
||||
inferrable_store("deopt");
|
||||
assertUnoptimized(inferrable_store);
|
28
deps/v8/test/mjsunit/regress/regress-crbug-605581.js
vendored
Normal file
28
deps/v8/test/mjsunit/regress/regress-crbug-605581.js
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --expose-debug-as debug
|
||||
|
||||
var Debug = debug.Debug;
|
||||
var exception = null;
|
||||
|
||||
function listener(event, exec_state, event_data, data) {
|
||||
if (event != Debug.DebugEvent.Break) return;
|
||||
try {
|
||||
assertThrows(() => exec_state.frame(0).evaluate("bar.baz"), ReferenceError);
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.setListener(listener);
|
||||
|
||||
(function() {
|
||||
debugger; // bar is still in TDZ at this point.
|
||||
let bar = 1;
|
||||
(x => bar); // force bar to be context-allocated.
|
||||
})();
|
||||
|
||||
Debug.setListener(null);
|
||||
assertNull(exception);
|
5
deps/v8/test/mjsunit/regress/regress-v8-4972.js
vendored
Normal file
5
deps/v8/test/mjsunit/regress/regress-v8-4972.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
new class extends new Proxy(class {},{}) {}
|
1
deps/v8/test/mjsunit/undetectable-compare.js
vendored
1
deps/v8/test/mjsunit/undetectable-compare.js
vendored
@ -92,5 +92,4 @@ for (var i = 0; i < 5; i++) {
|
||||
}
|
||||
|
||||
|
||||
assertFalse(undetectable == %GetUndetectable());
|
||||
assertFalse(undetectable === %GetUndetectable());
|
||||
|
@ -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
vendored
2
deps/v8/tools/gen-postmortem-metadata.py
vendored
@ -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…
x
Reference in New Issue
Block a user