diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-06-06 10:28:14 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-06-07 10:33:31 +0200 |
commit | 3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09 (patch) | |
tree | 9dee56e142638b34f1eccbd0ad88c3bce5377c29 /deps/v8/src/code-stub-assembler.cc | |
parent | 91a1bbe3055a660194ca4d403795aa0c03e9d056 (diff) | |
download | node-new-3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09.tar.gz |
deps: update V8 to 5.9.211.32
PR-URL: https://github.com/nodejs/node/pull/13263
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Diffstat (limited to 'deps/v8/src/code-stub-assembler.cc')
-rw-r--r-- | deps/v8/src/code-stub-assembler.cc | 2298 |
1 files changed, 1217 insertions, 1081 deletions
diff --git a/deps/v8/src/code-stub-assembler.cc b/deps/v8/src/code-stub-assembler.cc index e1ab040ab5..7b062b6bf6 100644 --- a/deps/v8/src/code-stub-assembler.cc +++ b/deps/v8/src/code-stub-assembler.cc @@ -58,7 +58,7 @@ void CodeStubAssembler::Assert(const NodeGenerator& codition_body, Node* condition = codition_body(); DCHECK_NOT_NULL(condition); Branch(condition, &ok, ¬_ok); - Bind(¬_ok); + BIND(¬_ok); if (message != nullptr) { char chars[1024]; Vector<char> buffer(chars); @@ -74,7 +74,7 @@ void CodeStubAssembler::Assert(const NodeGenerator& codition_body, } DebugBreak(); Goto(&ok); - Bind(&ok); + BIND(&ok); Comment("] Assert"); } #endif @@ -83,22 +83,22 @@ void CodeStubAssembler::Assert(const NodeGenerator& codition_body, Node* CodeStubAssembler::Select(Node* condition, const NodeGenerator& true_body, const NodeGenerator& false_body, MachineRepresentation rep) { - Variable value(this, rep); + VARIABLE(value, rep); Label vtrue(this), vfalse(this), end(this); Branch(condition, &vtrue, &vfalse); - Bind(&vtrue); + BIND(&vtrue); { value.Bind(true_body()); Goto(&end); } - Bind(&vfalse); + BIND(&vfalse); { value.Bind(false_body()); Goto(&end); } - Bind(&end); + BIND(&end); return value.value(); } @@ -212,14 +212,14 @@ Node* CodeStubAssembler::Float64Round(Node* x) { Label return_x(this); // Round up {x} towards Infinity. - Variable var_x(this, MachineRepresentation::kFloat64, Float64Ceil(x)); + VARIABLE(var_x, MachineRepresentation::kFloat64, Float64Ceil(x)); GotoIf(Float64LessThanOrEqual(Float64Sub(var_x.value(), one_half), x), &return_x); var_x.Bind(Float64Sub(var_x.value(), one)); Goto(&return_x); - Bind(&return_x); + BIND(&return_x); return var_x.value(); } @@ -233,7 +233,7 @@ Node* CodeStubAssembler::Float64Ceil(Node* x) { Node* two_52 = Float64Constant(4503599627370496.0E0); Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); - Variable var_x(this, MachineRepresentation::kFloat64, x); + VARIABLE(var_x, MachineRepresentation::kFloat64, x); Label return_x(this), return_minus_x(this); // Check if {x} is greater than zero. @@ -241,7 +241,7 @@ Node* CodeStubAssembler::Float64Ceil(Node* x) { Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero, &if_xnotgreaterthanzero); - Bind(&if_xgreaterthanzero); + BIND(&if_xgreaterthanzero); { // Just return {x} unless it's in the range ]0,2^52[. GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x); @@ -253,7 +253,7 @@ Node* CodeStubAssembler::Float64Ceil(Node* x) { Goto(&return_x); } - Bind(&if_xnotgreaterthanzero); + BIND(&if_xnotgreaterthanzero); { // Just return {x} unless it's in the range ]-2^52,0[ GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x); @@ -267,11 +267,11 @@ Node* CodeStubAssembler::Float64Ceil(Node* x) { Goto(&return_minus_x); } - Bind(&return_minus_x); + BIND(&return_minus_x); var_x.Bind(Float64Neg(var_x.value())); Goto(&return_x); - Bind(&return_x); + BIND(&return_x); return var_x.value(); } @@ -285,7 +285,7 @@ Node* CodeStubAssembler::Float64Floor(Node* x) { Node* two_52 = Float64Constant(4503599627370496.0E0); Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); - Variable var_x(this, MachineRepresentation::kFloat64, x); + VARIABLE(var_x, MachineRepresentation::kFloat64, x); Label return_x(this), return_minus_x(this); // Check if {x} is greater than zero. @@ -293,7 +293,7 @@ Node* CodeStubAssembler::Float64Floor(Node* x) { Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero, &if_xnotgreaterthanzero); - Bind(&if_xgreaterthanzero); + BIND(&if_xgreaterthanzero); { // Just return {x} unless it's in the range ]0,2^52[. GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x); @@ -305,7 +305,7 @@ Node* CodeStubAssembler::Float64Floor(Node* x) { Goto(&return_x); } - Bind(&if_xnotgreaterthanzero); + BIND(&if_xnotgreaterthanzero); { // Just return {x} unless it's in the range ]-2^52,0[ GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x); @@ -319,11 +319,11 @@ Node* CodeStubAssembler::Float64Floor(Node* x) { Goto(&return_minus_x); } - Bind(&return_minus_x); + BIND(&return_minus_x); var_x.Bind(Float64Neg(var_x.value())); Goto(&return_x); - Bind(&return_x); + BIND(&return_x); return var_x.value(); } @@ -335,7 +335,7 @@ Node* CodeStubAssembler::Float64RoundToEven(Node* x) { Node* f = Float64Floor(x); Node* f_and_half = Float64Add(f, Float64Constant(0.5)); - Variable var_result(this, MachineRepresentation::kFloat64); + VARIABLE(var_result, MachineRepresentation::kFloat64); Label return_f(this), return_f_plus_one(this), done(this); GotoIf(Float64LessThan(f_and_half, x), &return_f_plus_one); @@ -346,15 +346,15 @@ Node* CodeStubAssembler::Float64RoundToEven(Node* x) { &return_f_plus_one); } - Bind(&return_f); + BIND(&return_f); var_result.Bind(f); Goto(&done); - Bind(&return_f_plus_one); + BIND(&return_f_plus_one); var_result.Bind(Float64Add(f, Float64Constant(1.0))); Goto(&done); - Bind(&done); + BIND(&done); return var_result.value(); } @@ -368,7 +368,7 @@ Node* CodeStubAssembler::Float64Trunc(Node* x) { Node* two_52 = Float64Constant(4503599627370496.0E0); Node* minus_two_52 = Float64Constant(-4503599627370496.0E0); - Variable var_x(this, MachineRepresentation::kFloat64, x); + VARIABLE(var_x, MachineRepresentation::kFloat64, x); Label return_x(this), return_minus_x(this); // Check if {x} is greater than 0. @@ -376,7 +376,7 @@ Node* CodeStubAssembler::Float64Trunc(Node* x) { Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero, &if_xnotgreaterthanzero); - Bind(&if_xgreaterthanzero); + BIND(&if_xgreaterthanzero); { if (IsFloat64RoundDownSupported()) { var_x.Bind(Float64RoundDown(x)); @@ -392,7 +392,7 @@ Node* CodeStubAssembler::Float64Trunc(Node* x) { Goto(&return_x); } - Bind(&if_xnotgreaterthanzero); + BIND(&if_xnotgreaterthanzero); { if (IsFloat64RoundUpSupported()) { var_x.Bind(Float64RoundUp(x)); @@ -411,11 +411,11 @@ Node* CodeStubAssembler::Float64Trunc(Node* x) { } } - Bind(&return_minus_x); + BIND(&return_minus_x); var_x.Bind(Float64Neg(var_x.value())); Goto(&return_x); - Bind(&return_x); + BIND(&return_x); return var_x.value(); } @@ -458,7 +458,7 @@ Node* CodeStubAssembler::SmiMin(Node* a, Node* b) { } Node* CodeStubAssembler::SmiMod(Node* a, Node* b) { - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); Label return_result(this, &var_result), return_minuszero(this, Label::kDeferred), return_nan(this, Label::kDeferred); @@ -475,7 +475,7 @@ Node* CodeStubAssembler::SmiMod(Node* a, Node* b) { Branch(Int32LessThanOrEqual(Int32Constant(0), a), &if_aisnotnegative, &if_aisnegative); - Bind(&if_aisnotnegative); + BIND(&if_aisnotnegative); { // Fast case, don't need to check any other edge cases. Node* r = Int32Mod(a, b); @@ -483,7 +483,7 @@ Node* CodeStubAssembler::SmiMod(Node* a, Node* b) { Goto(&return_result); } - Bind(&if_aisnegative); + BIND(&if_aisnegative); { if (SmiValuesAre32Bits()) { // Check if {a} is kMinInt and {b} is -1 (only relevant if the @@ -492,7 +492,7 @@ Node* CodeStubAssembler::SmiMod(Node* a, Node* b) { GotoIfNot(Word32Equal(a, Int32Constant(kMinInt)), &join); GotoIf(Word32Equal(b, Int32Constant(-1)), &return_minuszero); Goto(&join); - Bind(&join); + BIND(&join); } // Perform the integer modulus operation. @@ -508,22 +508,22 @@ Node* CodeStubAssembler::SmiMod(Node* a, Node* b) { Goto(&return_result); } - Bind(&return_minuszero); + BIND(&return_minuszero); var_result.Bind(MinusZeroConstant()); Goto(&return_result); - Bind(&return_nan); + BIND(&return_nan); var_result.Bind(NanConstant()); Goto(&return_result); - Bind(&return_result); + BIND(&return_result); return var_result.value(); } Node* CodeStubAssembler::SmiMul(Node* a, Node* b) { - Variable var_result(this, MachineRepresentation::kTagged); - Variable var_lhs_float64(this, MachineRepresentation::kFloat64), - var_rhs_float64(this, MachineRepresentation::kFloat64); + VARIABLE(var_result, MachineRepresentation::kTagged); + VARIABLE(var_lhs_float64, MachineRepresentation::kFloat64); + VARIABLE(var_rhs_float64, MachineRepresentation::kFloat64); Label return_result(this, &var_result); // Both {a} and {b} are Smis. Convert them to integers and multiply. @@ -536,7 +536,7 @@ Node* CodeStubAssembler::SmiMul(Node* a, Node* b) { // Check if the multiplication overflowed. Label if_overflow(this, Label::kDeferred), if_notoverflow(this); Branch(overflow, &if_overflow, &if_notoverflow); - Bind(&if_notoverflow); + BIND(&if_notoverflow); { // If the answer is zero, we may need to return -0.0, depending on the // input. @@ -544,30 +544,30 @@ Node* CodeStubAssembler::SmiMul(Node* a, Node* b) { Node* answer = Projection(0, pair); Node* zero = Int32Constant(0); Branch(Word32Equal(answer, zero), &answer_zero, &answer_not_zero); - Bind(&answer_not_zero); + BIND(&answer_not_zero); { var_result.Bind(ChangeInt32ToTagged(answer)); Goto(&return_result); } - Bind(&answer_zero); + BIND(&answer_zero); { Node* or_result = Word32Or(lhs32, rhs32); Label if_should_be_negative_zero(this), if_should_be_zero(this); Branch(Int32LessThan(or_result, zero), &if_should_be_negative_zero, &if_should_be_zero); - Bind(&if_should_be_negative_zero); + BIND(&if_should_be_negative_zero); { var_result.Bind(MinusZeroConstant()); Goto(&return_result); } - Bind(&if_should_be_zero); + BIND(&if_should_be_zero); { var_result.Bind(SmiConstant(0)); Goto(&return_result); } } } - Bind(&if_overflow); + BIND(&if_overflow); { var_lhs_float64.Bind(SmiToFloat64(a)); var_rhs_float64.Bind(SmiToFloat64(b)); @@ -577,10 +577,57 @@ Node* CodeStubAssembler::SmiMul(Node* a, Node* b) { Goto(&return_result); } - Bind(&return_result); + BIND(&return_result); return var_result.value(); } +Node* CodeStubAssembler::TrySmiDiv(Node* dividend, Node* divisor, + Label* bailout) { + // Both {a} and {b} are Smis. Bailout to floating point division if {divisor} + // is zero. + GotoIf(WordEqual(divisor, SmiConstant(0)), bailout); + + // Do floating point division if {dividend} is zero and {divisor} is + // negative. + Label dividend_is_zero(this), dividend_is_not_zero(this); + Branch(WordEqual(dividend, SmiConstant(0)), ÷nd_is_zero, + ÷nd_is_not_zero); + + Bind(÷nd_is_zero); + { + GotoIf(SmiLessThan(divisor, SmiConstant(0)), bailout); + Goto(÷nd_is_not_zero); + } + Bind(÷nd_is_not_zero); + + Node* untagged_divisor = SmiToWord32(divisor); + Node* untagged_dividend = SmiToWord32(dividend); + + // Do floating point division if {dividend} is kMinInt (or kMinInt - 1 + // if the Smi size is 31) and {divisor} is -1. + Label divisor_is_minus_one(this), divisor_is_not_minus_one(this); + Branch(Word32Equal(untagged_divisor, Int32Constant(-1)), + &divisor_is_minus_one, &divisor_is_not_minus_one); + + Bind(&divisor_is_minus_one); + { + GotoIf(Word32Equal( + untagged_dividend, + Int32Constant(kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))), + bailout); + Goto(&divisor_is_not_minus_one); + } + Bind(&divisor_is_not_minus_one); + + Node* untagged_result = Int32Div(untagged_dividend, untagged_divisor); + Node* truncated = Int32Mul(untagged_result, untagged_divisor); + + // Do floating point division if the remainder is not 0. + GotoIf(Word32NotEqual(untagged_dividend, truncated), bailout); + + return SmiFromWord32(untagged_result); +} + Node* CodeStubAssembler::TruncateWordToWord32(Node* value) { if (Is64()) { return TruncateInt64ToInt32(value); @@ -613,12 +660,12 @@ Node* CodeStubAssembler::WordIsWordAligned(Node* word) { void CodeStubAssembler::BranchIfPrototypesHaveNoElements( Node* receiver_map, Label* definitely_no_elements, Label* possibly_elements) { - Variable var_map(this, MachineRepresentation::kTagged, receiver_map); + VARIABLE(var_map, MachineRepresentation::kTagged, receiver_map); Label loop_body(this, &var_map); Node* empty_elements = LoadRoot(Heap::kEmptyFixedArrayRootIndex); Goto(&loop_body); - Bind(&loop_body); + BIND(&loop_body); { Node* map = var_map.value(); Node* prototype = LoadMapPrototype(map); @@ -680,24 +727,24 @@ void CodeStubAssembler::BranchIfFastJSArray( BranchIfPrototypesHaveNoElements(map, if_true, if_false); } -Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes, - AllocationFlags flags, - Node* top_address, - Node* limit_address) { +Node* CodeStubAssembler::AllocateRaw(Node* size_in_bytes, AllocationFlags flags, + Node* top_address, Node* limit_address) { Node* top = Load(MachineType::Pointer(), top_address); Node* limit = Load(MachineType::Pointer(), limit_address); // If there's not enough space, call the runtime. - Variable result(this, MachineRepresentation::kTagged); + VARIABLE(result, MachineRepresentation::kTagged); Label runtime_call(this, Label::kDeferred), no_runtime_call(this); Label merge_runtime(this, &result); + bool needs_double_alignment = flags & kDoubleAlignment; + if (flags & kAllowLargeObjectAllocation) { Label next(this); GotoIf(IsRegularHeapObjectSize(size_in_bytes), &next); Node* runtime_flags = SmiConstant( - Smi::FromInt(AllocateDoubleAlignFlag::encode(false) | + Smi::FromInt(AllocateDoubleAlignFlag::encode(needs_double_alignment) | AllocateTargetSpace::encode(AllocationSpace::LO_SPACE))); Node* const runtime_result = CallRuntime(Runtime::kAllocateInTargetSpace, NoContextConstant(), @@ -705,18 +752,35 @@ Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes, result.Bind(runtime_result); Goto(&merge_runtime); - Bind(&next); + BIND(&next); } - Node* new_top = IntPtrAdd(top, size_in_bytes); + VARIABLE(adjusted_size, MachineType::PointerRepresentation(), size_in_bytes); + + if (needs_double_alignment) { + Label not_aligned(this), done_alignment(this, &adjusted_size); + + Branch(WordAnd(top, IntPtrConstant(kDoubleAlignmentMask)), ¬_aligned, + &done_alignment); + + BIND(¬_aligned); + Node* not_aligned_size = IntPtrAdd(size_in_bytes, IntPtrConstant(4)); + adjusted_size.Bind(not_aligned_size); + Goto(&done_alignment); + + BIND(&done_alignment); + } + + Node* new_top = IntPtrAdd(top, adjusted_size.value()); + Branch(UintPtrGreaterThanOrEqual(new_top, limit), &runtime_call, &no_runtime_call); - Bind(&runtime_call); + BIND(&runtime_call); Node* runtime_result; if (flags & kPretenured) { Node* runtime_flags = SmiConstant( - Smi::FromInt(AllocateDoubleAlignFlag::encode(false) | + Smi::FromInt(AllocateDoubleAlignFlag::encode(needs_double_alignment) | AllocateTargetSpace::encode(AllocationSpace::OLD_SPACE))); runtime_result = CallRuntime(Runtime::kAllocateInTargetSpace, NoContextConstant(), @@ -729,69 +793,68 @@ Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes, Goto(&merge_runtime); // When there is enough space, return `top' and bump it up. - Bind(&no_runtime_call); + BIND(&no_runtime_call); Node* no_runtime_result = top; StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address, new_top); - no_runtime_result = BitcastWordToTagged( - IntPtrAdd(no_runtime_result, IntPtrConstant(kHeapObjectTag))); - result.Bind(no_runtime_result); - Goto(&merge_runtime); - Bind(&merge_runtime); - return result.value(); -} + VARIABLE(address, MachineType::PointerRepresentation(), no_runtime_result); -Node* CodeStubAssembler::AllocateRawAligned(Node* size_in_bytes, - AllocationFlags flags, - Node* top_address, - Node* limit_address) { - Node* top = Load(MachineType::Pointer(), top_address); - Node* limit = Load(MachineType::Pointer(), limit_address); - Variable adjusted_size(this, MachineType::PointerRepresentation(), - size_in_bytes); - if (flags & kDoubleAlignment) { - Label aligned(this), not_aligned(this), merge(this, &adjusted_size); - Branch(WordAnd(top, IntPtrConstant(kDoubleAlignmentMask)), ¬_aligned, - &aligned); + if (needs_double_alignment) { + Label needs_filler(this), done_filling(this, &address); + Branch(IntPtrEqual(adjusted_size.value(), size_in_bytes), &done_filling, + &needs_filler); - Bind(¬_aligned); - Node* not_aligned_size = - IntPtrAdd(size_in_bytes, IntPtrConstant(kPointerSize)); - adjusted_size.Bind(not_aligned_size); - Goto(&merge); + BIND(&needs_filler); + // Store a filler and increase the address by kPointerSize. + StoreNoWriteBarrier(MachineRepresentation::kTagged, top, + LoadRoot(Heap::kOnePointerFillerMapRootIndex)); + address.Bind(IntPtrAdd(no_runtime_result, IntPtrConstant(4))); - Bind(&aligned); - Goto(&merge); + Goto(&done_filling); - Bind(&merge); + BIND(&done_filling); } - Variable address( - this, MachineRepresentation::kTagged, - AllocateRawUnaligned(adjusted_size.value(), kNone, top, limit)); + no_runtime_result = BitcastWordToTagged( + IntPtrAdd(address.value(), IntPtrConstant(kHeapObjectTag))); - Label needs_filler(this), doesnt_need_filler(this), - merge_address(this, &address); - Branch(IntPtrEqual(adjusted_size.value(), size_in_bytes), &doesnt_need_filler, - &needs_filler); + result.Bind(no_runtime_result); + Goto(&merge_runtime); - Bind(&needs_filler); - // Store a filler and increase the address by kPointerSize. - StoreNoWriteBarrier(MachineType::PointerRepresentation(), top, - LoadRoot(Heap::kOnePointerFillerMapRootIndex)); - address.Bind(BitcastWordToTagged( - IntPtrAdd(address.value(), IntPtrConstant(kPointerSize)))); - Goto(&merge_address); + BIND(&merge_runtime); + return result.value(); +} - Bind(&doesnt_need_filler); - Goto(&merge_address); +Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes, + AllocationFlags flags, + Node* top_address, + Node* limit_address) { + DCHECK((flags & kDoubleAlignment) == 0); + return AllocateRaw(size_in_bytes, flags, top_address, limit_address); +} + +Node* CodeStubAssembler::AllocateRawDoubleAligned(Node* size_in_bytes, + AllocationFlags flags, + Node* top_address, + Node* limit_address) { +#if defined(V8_HOST_ARCH_32_BIT) + return AllocateRaw(size_in_bytes, flags | kDoubleAlignment, top_address, + limit_address); +#elif defined(V8_HOST_ARCH_64_BIT) + // Allocation on 64 bit machine is naturally double aligned + return AllocateRaw(size_in_bytes, flags & ~kDoubleAlignment, top_address, + limit_address); +#else +#error Architecture not supported +#endif +} - Bind(&merge_address); - // Update the top. - StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address, - IntPtrAdd(top, adjusted_size.value())); - return address.value(); +Node* CodeStubAssembler::AllocateInNewSpace(Node* size_in_bytes, + AllocationFlags flags) { + DCHECK(flags == kNone || flags == kDoubleAlignment); + CSA_ASSERT(this, IsRegularHeapObjectSize(size_in_bytes)); + return Allocate(size_in_bytes, flags); } Node* CodeStubAssembler::Allocate(Node* size_in_bytes, AllocationFlags flags) { @@ -813,13 +876,20 @@ Node* CodeStubAssembler::Allocate(Node* size_in_bytes, AllocationFlags flags) { .address()); Node* limit_address = IntPtrAdd(top_address, IntPtrConstant(kPointerSize)); -#ifdef V8_HOST_ARCH_32_BIT if (flags & kDoubleAlignment) { - return AllocateRawAligned(size_in_bytes, flags, top_address, limit_address); + return AllocateRawDoubleAligned(size_in_bytes, flags, top_address, + limit_address); + } else { + return AllocateRawUnaligned(size_in_bytes, flags, top_address, + limit_address); } -#endif +} - return AllocateRawUnaligned(size_in_bytes, flags, top_address, limit_address); +Node* CodeStubAssembler::AllocateInNewSpace(int size_in_bytes, + AllocationFlags flags) { + CHECK(flags == kNone || flags == kDoubleAlignment); + DCHECK_LE(size_in_bytes, kMaxRegularHeapObjectSize); + return CodeStubAssembler::Allocate(IntPtrConstant(size_in_bytes), flags); } Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) { @@ -850,13 +920,13 @@ void CodeStubAssembler::BranchIfToBooleanIsTrue(Node* value, Label* if_true, // Check if {value} is a Smi or a HeapObject. Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); - Bind(&if_valueissmi); + BIND(&if_valueissmi); { // The {value} is a Smi, only need to check against zero. BranchIfSmiEqual(value, SmiConstant(0), if_false, if_true); } - Bind(&if_valueisnotsmi); + BIND(&if_valueisnotsmi); { // Check if {value} is the empty string. GotoIf(IsEmptyString(value), if_false); @@ -877,7 +947,7 @@ void CodeStubAssembler::BranchIfToBooleanIsTrue(Node* value, Label* if_true, // that make it here yield true. Branch(IsHeapNumberMap(value_map), &if_valueisheapnumber, if_true); - Bind(&if_valueisheapnumber); + BIND(&if_valueisheapnumber); { // Load the floating point value of {value}. Node* value_value = LoadObjectField(value, HeapNumber::kValueOffset, @@ -1109,12 +1179,12 @@ Node* CodeStubAssembler::LoadMapConstructorFunctionIndex(Node* map) { Node* CodeStubAssembler::LoadMapConstructor(Node* map) { CSA_SLOW_ASSERT(this, IsMap(map)); - Variable result(this, MachineRepresentation::kTagged, - LoadObjectField(map, Map::kConstructorOrBackPointerOffset)); + VARIABLE(result, MachineRepresentation::kTagged, + LoadObjectField(map, Map::kConstructorOrBackPointerOffset)); Label done(this), loop(this, &result); Goto(&loop); - Bind(&loop); + BIND(&loop); { GotoIf(TaggedIsSmi(result.value()), &done); Node* is_map_type = @@ -1124,7 +1194,7 @@ Node* CodeStubAssembler::LoadMapConstructor(Node* map) { LoadObjectField(result.value(), Map::kConstructorOrBackPointerOffset)); Goto(&loop); } - Bind(&done); + BIND(&done); return result.value(); } @@ -1235,6 +1305,32 @@ Node* CodeStubAssembler::LoadFixedTypedArrayElement( return Load(type, data_pointer, offset); } +Node* CodeStubAssembler::LoadFixedTypedArrayElementAsTagged( + Node* data_pointer, Node* index_node, ElementsKind elements_kind, + ParameterMode parameter_mode) { + Node* value = LoadFixedTypedArrayElement(data_pointer, index_node, + elements_kind, parameter_mode); + switch (elements_kind) { + case ElementsKind::INT8_ELEMENTS: + case ElementsKind::UINT8_CLAMPED_ELEMENTS: + case ElementsKind::UINT8_ELEMENTS: + case ElementsKind::INT16_ELEMENTS: + case ElementsKind::UINT16_ELEMENTS: + return SmiFromWord32(value); + case ElementsKind::INT32_ELEMENTS: + return ChangeInt32ToTagged(value); + case ElementsKind::UINT32_ELEMENTS: + return ChangeUint32ToTagged(value); + case ElementsKind::FLOAT32_ELEMENTS: + return AllocateHeapNumberWithValue(ChangeFloat32ToFloat64(value)); + case ElementsKind::FLOAT64_ELEMENTS: + return AllocateHeapNumberWithValue(value); + default: + UNREACHABLE(); + return nullptr; + } +} + Node* CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement( Node* object, Node* index_node, int additional_offset, ParameterMode parameter_mode) { @@ -1435,12 +1531,11 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); Label pre_bailout(this); Label success(this); - Variable var_tagged_length(this, MachineRepresentation::kTagged); + VARIABLE(var_tagged_length, MachineRepresentation::kTagged); ParameterMode mode = OptimalParameterMode(); - Variable var_length(this, OptimalParameterRepresentation(), - TaggedToParameter(LoadJSArrayLength(array), mode)); - Variable var_elements(this, MachineRepresentation::kTagged, - LoadElements(array)); + VARIABLE(var_length, OptimalParameterRepresentation(), + TaggedToParameter(LoadJSArrayLength(array), mode)); + VARIABLE(var_elements, MachineRepresentation::kTagged, LoadElements(array)); Node* capacity = TaggedToParameter(LoadFixedArrayBaseLength(var_elements.value()), mode); @@ -1456,7 +1551,7 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, kind, capacity, new_capacity, mode, &pre_bailout)); Goto(&fits); - Bind(&fits); + BIND(&fits); Node* elements = var_elements.value(); // Push each argument onto the end of the array now that there is enough @@ -1491,7 +1586,7 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, Goto(&success); } - Bind(&pre_bailout); + BIND(&pre_bailout); { Node* length = ParameterToTagged(var_length.value(), mode); var_tagged_length.Bind(length); @@ -1501,7 +1596,7 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, Goto(bailout); } - Bind(&success); + BIND(&success); return var_tagged_length.value(); } @@ -1543,7 +1638,7 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, ParameterMode mode, AllocationFlags flags) { Comment("AllocateSeqOneByteString"); - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); // Compute the SeqOneByteString size and check if it fits into new space. Label if_lengthiszero(this), if_sizeissmall(this), @@ -1557,10 +1652,10 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), &if_sizeissmall, &if_notsizeissmall); - Bind(&if_sizeissmall); + BIND(&if_sizeissmall); { // Just allocate the SeqOneByteString in new space. - Node* result = Allocate(size, flags); + Node* result = AllocateInNewSpace(size, flags); DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex)); StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex); StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, @@ -1573,7 +1668,7 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, Goto(&if_join); } - Bind(&if_notsizeissmall); + BIND(&if_notsizeissmall); { // We might need to allocate in large object space, go to the runtime. Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context, @@ -1582,13 +1677,13 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, Goto(&if_join); } - Bind(&if_lengthiszero); + BIND(&if_lengthiszero); { var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex)); Goto(&if_join); } - Bind(&if_join); + BIND(&if_join); return var_result.value(); } @@ -1614,7 +1709,7 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, ParameterMode mode, AllocationFlags flags) { Comment("AllocateSeqTwoByteString"); - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); // Compute the SeqTwoByteString size and check if it fits into new space. Label if_lengthiszero(this), if_sizeissmall(this), @@ -1628,10 +1723,10 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)), &if_sizeissmall, &if_notsizeissmall); - Bind(&if_sizeissmall); + BIND(&if_sizeissmall); { // Just allocate the SeqTwoByteString in new space. - Node* result = Allocate(size, flags); + Node* result = AllocateInNewSpace(size, flags); DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex)); StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex); StoreObjectFieldNoWriteBarrier( @@ -1645,7 +1740,7 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, Goto(&if_join); } - Bind(&if_notsizeissmall); + BIND(&if_notsizeissmall); { // We might need to allocate in large object space, go to the runtime. Node* result = @@ -1655,13 +1750,13 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, Goto(&if_join); } - Bind(&if_lengthiszero); + BIND(&if_lengthiszero); { var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex)); Goto(&if_join); } - Bind(&if_join); + BIND(&if_join); return var_result.value(); } @@ -1765,7 +1860,7 @@ Node* CodeStubAssembler::NewConsString(Node* context, Node* length, Node* left, STATIC_ASSERT(kOneByteDataHintTag != 0); Label one_byte_map(this); Label two_byte_map(this); - Variable result(this, MachineRepresentation::kTagged); + VARIABLE(result, MachineRepresentation::kTagged); Label done(this, &result); GotoIf(Word32NotEqual(Word32And(anded_instance_types, Int32Constant(kStringEncodingMask | @@ -1778,17 +1873,17 @@ Node* CodeStubAssembler::NewConsString(Node* context, Node* length, Node* left, Int32Constant(kOneByteStringTag | kOneByteDataHintTag)), &two_byte_map, &one_byte_map); - Bind(&one_byte_map); + BIND(&one_byte_map); Comment("One-byte ConsString"); result.Bind(AllocateOneByteConsString(length, left, right, flags)); Goto(&done); - Bind(&two_byte_map); + BIND(&two_byte_map); Comment("Two-byte ConsString"); result.Bind(AllocateTwoByteConsString(length, left, right, flags)); Goto(&done); - Bind(&done); + BIND(&done); return result.value(); } @@ -1853,7 +1948,7 @@ Node* CodeStubAssembler::AllocateNameDictionary(Node* at_least_space_for) { IntPtrAdd(WordShl(length, IntPtrConstant(kPointerSizeLog2)), IntPtrConstant(NameDictionary::kHeaderSize)); - Node* result = Allocate(store_size); + Node* result = AllocateInNewSpace(store_size); Comment("Initialize NameDictionary"); // Initialize FixedArray fields. DCHECK(Heap::RootIsImmortalImmovable(Heap::kHashTableMapRootIndex)); @@ -1894,8 +1989,7 @@ Node* CodeStubAssembler::AllocateJSObjectFromMap(Node* map, Node* properties, CSA_ASSERT(this, IsMap(map)); Node* size = IntPtrMul(LoadMapInstanceSize(map), IntPtrConstant(kPointerSize)); - CSA_ASSERT(this, IsRegularHeapObjectSize(size)); - Node* object = Allocate(size, flags); + Node* object = AllocateInNewSpace(size, flags); StoreMapNoWriteBarrier(object, map); InitializeJSObjectFromMap(object, map, size, properties, elements); return object; @@ -1996,7 +2090,8 @@ Node* CodeStubAssembler::AllocateUninitializedJSArray(ElementsKind kind, Node* length, Node* allocation_site, Node* size_in_bytes) { - Node* array = Allocate(size_in_bytes); + // Allocate space for the JSArray and the elements FixedArray in one go. + Node* array = AllocateInNewSpace(size_in_bytes); Comment("write JSArray headers"); StoreMapNoWriteBarrier(array, array_map); @@ -2147,12 +2242,12 @@ void CodeStubAssembler::CopyFixedArrayElements( Node* limit_offset = ElementOffsetFromIndex( IntPtrOrSmiConstant(0, mode), from_kind, mode, first_element_offset); - Variable var_from_offset(this, MachineType::PointerRepresentation(), - ElementOffsetFromIndex(element_count, from_kind, - mode, first_element_offset)); + VARIABLE(var_from_offset, MachineType::PointerRepresentation(), + ElementOffsetFromIndex(element_count, from_kind, mode, + first_element_offset)); // This second variable is used only when the element sizes of source and // destination arrays do not match. - Variable var_to_offset(this, MachineType::PointerRepresentation()); + VARIABLE(var_to_offset, MachineType::PointerRepresentation()); if (element_size_matches) { var_to_offset.Bind(var_from_offset.value()); } else { @@ -2165,7 +2260,7 @@ void CodeStubAssembler::CopyFixedArrayElements( Branch(WordEqual(var_from_offset.value(), limit_offset), &done, &decrement); - Bind(&decrement); + BIND(&decrement); { Node* from_offset = IntPtrSub( var_from_offset.value(), @@ -2210,7 +2305,7 @@ void CodeStubAssembler::CopyFixedArrayElements( Goto(&next_iter); if (if_hole == &store_double_hole) { - Bind(&store_double_hole); + BIND(&store_double_hole); // Don't use doubles to store the hole double, since manipulating the // signaling NaN used for the hole in C++, e.g. with bit_cast, will // change its value on ia32 (the x87 stack is used to return values @@ -2232,12 +2327,12 @@ void CodeStubAssembler::CopyFixedArrayElements( Goto(&next_iter); } - Bind(&next_iter); + BIND(&next_iter); Node* compare = WordNotEqual(from_offset, limit_offset); Branch(compare, &decrement, &done); } - Bind(&done); + BIND(&done); IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); Comment("] CopyFixedArrayElements"); } @@ -2274,8 +2369,7 @@ void CodeStubAssembler::CopyStringCharacters(Node* from_string, Node* to_string, int from_increment = 1 << ElementsKindToShiftSize(from_kind); int to_increment = 1 << ElementsKindToShiftSize(to_kind); - Variable current_to_offset(this, MachineType::PointerRepresentation(), - to_offset); + VARIABLE(current_to_offset, MachineType::PointerRepresentation(), to_offset); VariableList vars({¤t_to_offset}, zone()); int to_index_constant = 0, from_index_constant = 0; Smi* to_index_smi = nullptr; @@ -2419,45 +2513,45 @@ void CodeStubAssembler::InitializeAllocationMemento(Node* base_allocation, Node* CodeStubAssembler::TryTaggedToFloat64(Node* value, Label* if_valueisnotnumber) { Label out(this); - Variable var_result(this, MachineRepresentation::kFloat64); + VARIABLE(var_result, MachineRepresentation::kFloat64); // Check if the {value} is a Smi or a HeapObject. Label if_valueissmi(this), if_valueisnotsmi(this); Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); - Bind(&if_valueissmi); + BIND(&if_valueissmi); { // Convert the Smi {value}. var_result.Bind(SmiToFloat64(value)); Goto(&out); } - Bind(&if_valueisnotsmi); + BIND(&if_valueisnotsmi); { // Check if {value} is a HeapNumber. Label if_valueisheapnumber(this); Branch(IsHeapNumberMap(LoadMap(value)), &if_valueisheapnumber, if_valueisnotnumber); - Bind(&if_valueisheapnumber); + BIND(&if_valueisheapnumber); { // Load the floating point value. var_result.Bind(LoadHeapNumberValue(value)); Goto(&out); } } - Bind(&out); + BIND(&out); return var_result.value(); } Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) { // We might need to loop once due to ToNumber conversion. - Variable var_value(this, MachineRepresentation::kTagged), - var_result(this, MachineRepresentation::kFloat64); + VARIABLE(var_value, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kFloat64); Label loop(this, &var_value), done_loop(this, &var_result); var_value.Bind(value); Goto(&loop); - Bind(&loop); + BIND(&loop); { Label if_valueisnotnumber(this, Label::kDeferred); @@ -2470,7 +2564,7 @@ Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) { var_result.Bind(result); Goto(&done_loop); - Bind(&if_valueisnotnumber); + BIND(&if_valueisnotnumber); { // Convert the {value} to a Number first. Callable callable = CodeFactory::NonNumberToNumber(isolate()); @@ -2478,17 +2572,17 @@ Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) { Goto(&loop); } } - Bind(&done_loop); + BIND(&done_loop); return var_result.value(); } Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) { // We might need to loop once due to ToNumber conversion. - Variable var_value(this, MachineRepresentation::kTagged, value), - var_result(this, MachineRepresentation::kWord32); + VARIABLE(var_value, MachineRepresentation::kTagged, value); + VARIABLE(var_result, MachineRepresentation::kWord32); Label loop(this, &var_value), done_loop(this, &var_result); Goto(&loop); - Bind(&loop); + BIND(&loop); { // Load the current {value}. value = var_value.value(); @@ -2497,14 +2591,14 @@ Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) { Label if_valueissmi(this), if_valueisnotsmi(this); Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); - Bind(&if_valueissmi); + BIND(&if_valueissmi); { // Convert the Smi {value}. var_result.Bind(SmiToWord32(value)); Goto(&done_loop); } - Bind(&if_valueisnotsmi); + BIND(&if_valueisnotsmi); { // Check if {value} is a HeapNumber. Label if_valueisheapnumber(this), @@ -2512,14 +2606,14 @@ Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) { Branch(IsHeapNumberMap(LoadMap(value)), &if_valueisheapnumber, &if_valueisnotheapnumber); - Bind(&if_valueisheapnumber); + BIND(&if_valueisheapnumber); { // Truncate the floating point value. var_result.Bind(TruncateHeapNumberValueToWord32(value)); Goto(&done_loop); } - Bind(&if_valueisnotheapnumber); + BIND(&if_valueisnotheapnumber); { // Convert the {value} to a Number first. Callable callable = CodeFactory::NonNumberToNumber(isolate()); @@ -2528,7 +2622,7 @@ Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) { } } } - Bind(&done_loop); + BIND(&done_loop); return var_result.value(); } @@ -2545,17 +2639,17 @@ Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) { Label if_valueisequal(this), if_valueisnotequal(this); Branch(Float64Equal(value, value64), &if_valueisequal, &if_valueisnotequal); - Bind(&if_valueisequal); + BIND(&if_valueisequal); { GotoIfNot(Word32Equal(value32, Int32Constant(0)), &if_valueisint32); Branch(Int32LessThan(Float64ExtractHighWord32(value), Int32Constant(0)), &if_valueisheapnumber, &if_valueisint32); } - Bind(&if_valueisnotequal); + BIND(&if_valueisnotequal); Goto(&if_valueisheapnumber); - Variable var_result(this, MachineRepresentation::kTagged); - Bind(&if_valueisint32); + VARIABLE(var_result, MachineRepresentation::kTagged); + BIND(&if_valueisint32); { if (Is64()) { Node* result = SmiTag(ChangeInt32ToInt64(value32)); @@ -2566,9 +2660,9 @@ Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) { Node* overflow = Projection(1, pair); Label if_overflow(this, Label::kDeferred), if_notoverflow(this); Branch(overflow, &if_overflow, &if_notoverflow); - Bind(&if_overflow); + BIND(&if_overflow); Goto(&if_valueisheapnumber); - Bind(&if_notoverflow); + BIND(&if_notoverflow); { Node* result = BitcastWordToTaggedSigned(Projection(0, pair)); var_result.Bind(result); @@ -2576,13 +2670,13 @@ Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) { } } } - Bind(&if_valueisheapnumber); + BIND(&if_valueisheapnumber); { Node* result = AllocateHeapNumberWithValue(value); var_result.Bind(result); Goto(&if_join); } - Bind(&if_join); + BIND(&if_join); return var_result.value(); } @@ -2590,38 +2684,38 @@ Node* CodeStubAssembler::ChangeInt32ToTagged(Node* value) { if (Is64()) { return SmiTag(ChangeInt32ToInt64(value)); } - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); Node* pair = Int32AddWithOverflow(value, value); Node* overflow = Projection(1, pair); Label if_overflow(this, Label::kDeferred), if_notoverflow(this), if_join(this); Branch(overflow, &if_overflow, &if_notoverflow); - Bind(&if_overflow); + BIND(&if_overflow); { Node* value64 = ChangeInt32ToFloat64(value); Node* result = AllocateHeapNumberWithValue(value64); var_result.Bind(result); } Goto(&if_join); - Bind(&if_notoverflow); + BIND(&if_notoverflow); { Node* result = BitcastWordToTaggedSigned(Projection(0, pair)); var_result.Bind(result); } Goto(&if_join); - Bind(&if_join); + BIND(&if_join); return var_result.value(); } Node* CodeStubAssembler::ChangeUint32ToTagged(Node* value) { Label if_overflow(this, Label::kDeferred), if_not_overflow(this), if_join(this); - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); // If {value} > 2^31 - 1, we need to store it in a HeapNumber. Branch(Uint32LessThan(Int32Constant(Smi::kMaxValue), value), &if_overflow, &if_not_overflow); - Bind(&if_not_overflow); + BIND(&if_not_overflow); { if (Is64()) { var_result.Bind(SmiTag(ChangeUint32ToUint64(value))); @@ -2638,26 +2732,26 @@ Node* CodeStubAssembler::ChangeUint32ToTagged(Node* value) { } Goto(&if_join); - Bind(&if_overflow); + BIND(&if_overflow); { Node* float64_value = ChangeUint32ToFloat64(value); var_result.Bind(AllocateHeapNumberWithValue(float64_value)); } Goto(&if_join); - Bind(&if_join); + BIND(&if_join); return var_result.value(); } Node* CodeStubAssembler::ToThisString(Node* context, Node* value, char const* method_name) { - Variable var_value(this, MachineRepresentation::kTagged, value); + VARIABLE(var_value, MachineRepresentation::kTagged, value); // Check if the {value} is a Smi or a HeapObject. Label if_valueissmi(this, Label::kDeferred), if_valueisnotsmi(this), if_valueisstring(this); Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); - Bind(&if_valueisnotsmi); + BIND(&if_valueisnotsmi); { // Load the instance type of the {value}. Node* value_instance_type = LoadInstanceType(value); @@ -2666,7 +2760,7 @@ Node* CodeStubAssembler::ToThisString(Node* context, Node* value, Label if_valueisnotstring(this, Label::kDeferred); Branch(IsStringInstanceType(value_instance_type), &if_valueisstring, &if_valueisnotstring); - Bind(&if_valueisnotstring); + BIND(&if_valueisnotstring); { // Check if the {value} is null. Label if_valueisnullorundefined(this, Label::kDeferred), @@ -2674,12 +2768,12 @@ Node* CodeStubAssembler::ToThisString(Node* context, Node* value, if_valueisnotnull(this, Label::kDeferred); Branch(WordEqual(value, NullConstant()), &if_valueisnullorundefined, &if_valueisnotnull); - Bind(&if_valueisnotnull); + BIND(&if_valueisnotnull); { // Check if the {value} is undefined. Branch(WordEqual(value, UndefinedConstant()), &if_valueisnullorundefined, &if_valueisnotnullorundefined); - Bind(&if_valueisnotnullorundefined); + BIND(&if_valueisnotnullorundefined); { // Convert the {value} to a String. Callable callable = CodeFactory::ToString(isolate()); @@ -2688,7 +2782,7 @@ Node* CodeStubAssembler::ToThisString(Node* context, Node* value, } } - Bind(&if_valueisnullorundefined); + BIND(&if_valueisnullorundefined); { // The {value} is either null or undefined. CallRuntime(Runtime::kThrowCalledOnNullOrUndefined, context, @@ -2698,19 +2792,19 @@ Node* CodeStubAssembler::ToThisString(Node* context, Node* value, } } } - Bind(&if_valueissmi); + BIND(&if_valueissmi); { // The {value} is a Smi, convert it to a String. Callable callable = CodeFactory::NumberToString(isolate()); var_value.Bind(CallStub(callable, context, value)); Goto(&if_valueisstring); } - Bind(&if_valueisstring); + BIND(&if_valueisstring); return var_value.value(); } -Node* CodeStubAssembler::ChangeNumberToFloat64(compiler::Node* value) { - Variable result(this, MachineRepresentation::kFloat64); +Node* CodeStubAssembler::ChangeNumberToFloat64(Node* value) { + VARIABLE(result, MachineRepresentation::kFloat64); Label smi(this); Label done(this, &result); GotoIf(TaggedIsSmi(value), &smi); @@ -2718,13 +2812,30 @@ Node* CodeStubAssembler::ChangeNumberToFloat64(compiler::Node* value) { LoadObjectField(value, HeapNumber::kValueOffset, MachineType::Float64())); Goto(&done); - Bind(&smi); + BIND(&smi); { result.Bind(SmiToFloat64(value)); Goto(&done); } - Bind(&done); + BIND(&done); + return result.value(); +} + +Node* CodeStubAssembler::ChangeNumberToIntPtr(Node* value) { + VARIABLE(result, MachineType::PointerRepresentation()); + Label smi(this), done(this, &result); + GotoIf(TaggedIsSmi(value), &smi); + + CSA_ASSERT(this, IsHeapNumber(value)); + result.Bind(ChangeFloat64ToUintPtr(LoadHeapNumberValue(value))); + Goto(&done); + + BIND(&smi); + result.Bind(SmiToWord(value)); + Goto(&done); + + BIND(&done); return result.value(); } @@ -2732,11 +2843,11 @@ Node* CodeStubAssembler::ToThisValue(Node* context, Node* value, PrimitiveType primitive_type, char const* method_name) { // We might need to loop once due to JSValue unboxing. - Variable var_value(this, MachineRepresentation::kTagged, value); + VARIABLE(var_value, MachineRepresentation::kTagged, value); Label loop(this, &var_value), done_loop(this), done_throw(this, Label::kDeferred); Goto(&loop); - Bind(&loop); + BIND(&loop); { // Load the current {value}. value = var_value.value(); @@ -2757,14 +2868,14 @@ Node* CodeStubAssembler::ToThisValue(Node* context, Node* value, Branch(Word32Equal(value_instance_type, Int32Constant(JS_VALUE_TYPE)), &if_valueisvalue, &if_valueisnotvalue); - Bind(&if_valueisvalue); + BIND(&if_valueisvalue); { // Load the actual value from the {value}. var_value.Bind(LoadObjectField(value, JSValue::kValueOffset)); Goto(&loop); } - Bind(&if_valueisnotvalue); + BIND(&if_valueisnotvalue); { switch (primitive_type) { case PrimitiveType::kBoolean: @@ -2787,7 +2898,7 @@ Node* CodeStubAssembler::ToThisValue(Node* context, Node* value, } } - Bind(&done_throw); + BIND(&done_throw); { // The {value} is not a compatible receiver for this method. CallRuntime(Runtime::kThrowNotGeneric, context, @@ -2796,7 +2907,7 @@ Node* CodeStubAssembler::ToThisValue(Node* context, Node* value, Unreachable(); } - Bind(&done_loop); + BIND(&done_loop); return var_value.value(); } @@ -2804,7 +2915,7 @@ Node* CodeStubAssembler::ThrowIfNotInstanceType(Node* context, Node* value, InstanceType instance_type, char const* method_name) { Label out(this), throw_exception(this, Label::kDeferred); - Variable var_value_map(this, MachineRepresentation::kTagged); + VARIABLE(var_value_map, MachineRepresentation::kTagged); GotoIf(TaggedIsSmi(value), &throw_exception); @@ -2816,14 +2927,14 @@ Node* CodeStubAssembler::ThrowIfNotInstanceType(Node* context, Node* value, &throw_exception); // The {value} is not a compatible receiver for this method. - Bind(&throw_exception); + BIND(&throw_exception); CallRuntime( Runtime::kThrowIncompatibleMethodReceiver, context, HeapConstant(factory()->NewStringFromAsciiChecked(method_name, TENURED)), value); Unreachable(); - Bind(&out); + BIND(&out); return var_value_map.value(); } @@ -2857,6 +2968,11 @@ Node* CodeStubAssembler::IsCallableMap(Node* map) { Int32Constant(0)); } +Node* CodeStubAssembler::IsDeprecatedMap(Node* map) { + CSA_ASSERT(this, IsMap(map)); + return IsSetWord32<Map::Deprecated>(LoadMapBitField3(map)); +} + Node* CodeStubAssembler::IsCallable(Node* object) { return IsCallableMap(LoadMap(object)); } @@ -2879,6 +2995,36 @@ Node* CodeStubAssembler::IsStringInstanceType(Node* instance_type) { return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE)); } +Node* CodeStubAssembler::IsOneByteStringInstanceType(Node* instance_type) { + CSA_ASSERT(this, IsStringInstanceType(instance_type)); + return Word32Equal( + Word32And(instance_type, Int32Constant(kStringEncodingMask)), + Int32Constant(kOneByteStringTag)); +} + +Node* CodeStubAssembler::IsSequentialStringInstanceType(Node* instance_type) { + CSA_ASSERT(this, IsStringInstanceType(instance_type)); + return Word32Equal( + Word32And(instance_type, Int32Constant(kStringRepresentationMask)), + Int32Constant(kSeqStringTag)); +} + +Node* CodeStubAssembler::IsExternalStringInstanceType(Node* instance_type) { + CSA_ASSERT(this, IsStringInstanceType(instance_type)); + return Word32Equal( + Word32And(instance_type, Int32Constant(kStringRepresentationMask)), + Int32Constant(kExternalStringTag)); +} + +Node* CodeStubAssembler::IsShortExternalStringInstanceType( + Node* instance_type) { + CSA_ASSERT(this, IsStringInstanceType(instance_type)); + STATIC_ASSERT(kShortExternalStringTag != 0); + return Word32NotEqual( + Word32And(instance_type, Int32Constant(kShortExternalStringMask)), + Int32Constant(0)); +} + Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) { STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); return Int32GreaterThanOrEqual(instance_type, @@ -2919,13 +3065,21 @@ Node* CodeStubAssembler::IsJSArray(Node* object) { } Node* CodeStubAssembler::IsWeakCell(Node* object) { - return HasInstanceType(object, WEAK_CELL_TYPE); + return IsWeakCellMap(LoadMap(object)); } Node* CodeStubAssembler::IsBoolean(Node* object) { return IsBooleanMap(LoadMap(object)); } +Node* CodeStubAssembler::IsPropertyCell(Node* object) { + return IsPropertyCellMap(LoadMap(object)); +} + +Node* CodeStubAssembler::IsAccessorPair(Node* object) { + return IsAccessorPairMap(LoadMap(object)); +} + Node* CodeStubAssembler::IsHeapNumber(Node* object) { return IsHeapNumberMap(LoadMap(object)); } @@ -2936,8 +3090,8 @@ Node* CodeStubAssembler::IsName(Node* object) { } Node* CodeStubAssembler::IsString(Node* object) { - return Int32LessThanOrEqual(LoadInstanceType(object), - Int32Constant(FIRST_NONSTRING_TYPE)); + return Int32LessThan(LoadInstanceType(object), + Int32Constant(FIRST_NONSTRING_TYPE)); } Node* CodeStubAssembler::IsSymbol(Node* object) { @@ -2981,203 +3135,121 @@ Node* CodeStubAssembler::IsJSFunction(Node* object) { return HasInstanceType(object, JS_FUNCTION_TYPE); } +Node* CodeStubAssembler::IsJSTypedArray(Node* object) { + return HasInstanceType(object, JS_TYPED_ARRAY_TYPE); +} + +Node* CodeStubAssembler::IsFixedTypedArray(Node* object) { + Node* instance_type = LoadInstanceType(object); + return Word32And( + Int32GreaterThanOrEqual(instance_type, + Int32Constant(FIRST_FIXED_TYPED_ARRAY_TYPE)), + Int32LessThanOrEqual(instance_type, + Int32Constant(LAST_FIXED_TYPED_ARRAY_TYPE))); +} + +Node* CodeStubAssembler::IsJSRegExp(Node* object) { + return HasInstanceType(object, JS_REGEXP_TYPE); +} + +Node* CodeStubAssembler::IsNumber(Node* object) { + return Select(TaggedIsSmi(object), [=] { return Int32Constant(1); }, + [=] { return IsHeapNumber(object); }, + MachineRepresentation::kWord32); +} + +Node* CodeStubAssembler::IsNumberNormalized(Node* number) { + CSA_ASSERT(this, IsNumber(number)); + + VARIABLE(var_result, MachineRepresentation::kWord32, Int32Constant(1)); + Label out(this); + + GotoIf(TaggedIsSmi(number), &out); + + Node* const value = LoadHeapNumberValue(number); + Node* const smi_min = Float64Constant(static_cast<double>(Smi::kMinValue)); + Node* const smi_max = Float64Constant(static_cast<double>(Smi::kMaxValue)); + + GotoIf(Float64LessThan(value, smi_min), &out); + GotoIf(Float64GreaterThan(value, smi_max), &out); + GotoIfNot(Float64Equal(value, value), &out); // NaN. + + var_result.Bind(Int32Constant(0)); + Goto(&out); + + BIND(&out); + return var_result.value(); +} + Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index, ParameterMode parameter_mode) { + if (parameter_mode == SMI_PARAMETERS) CSA_ASSERT(this, TaggedIsSmi(index)); CSA_ASSERT(this, IsString(string)); - // Translate the {index} into a Word. - index = ParameterToWord(index, parameter_mode); - - // We may need to loop in case of cons, thin, or sliced strings. - Variable var_index(this, MachineType::PointerRepresentation(), index); - Variable var_string(this, MachineRepresentation::kTagged, string); - Variable var_result(this, MachineRepresentation::kWord32); - Variable* loop_vars[] = {&var_index, &var_string}; - Label done_loop(this, &var_result), loop(this, 2, loop_vars); - Goto(&loop); - Bind(&loop); - { - // Load the current {index}. - index = var_index.value(); - - // Load the current {string}. - string = var_string.value(); - // Load the instance type of the {string}. - Node* string_instance_type = LoadInstanceType(string); + // Translate the {index} into a Word. + Node* const int_index = ParameterToWord(index, parameter_mode); + CSA_ASSERT(this, IntPtrGreaterThanOrEqual(int_index, IntPtrConstant(0))); - // Check if the {string} is a SeqString. - Label if_stringissequential(this), if_stringisnotsequential(this); - Branch(Word32Equal(Word32And(string_instance_type, - Int32Constant(kStringRepresentationMask)), - Int32Constant(kSeqStringTag)), - &if_stringissequential, &if_stringisnotsequential); + VARIABLE(var_result, MachineRepresentation::kWord32); - Bind(&if_stringissequential); - { - // Check if the {string} is a TwoByteSeqString or a OneByteSeqString. - Label if_stringistwobyte(this), if_stringisonebyte(this); - Branch(Word32Equal(Word32And(string_instance_type, - Int32Constant(kStringEncodingMask)), - Int32Constant(kTwoByteStringTag)), - &if_stringistwobyte, &if_stringisonebyte); - - Bind(&if_stringisonebyte); - { - var_result.Bind( - Load(MachineType::Uint8(), string, - IntPtrAdd(index, IntPtrConstant(SeqOneByteString::kHeaderSize - - kHeapObjectTag)))); - Goto(&done_loop); - } + Label out(this, &var_result), runtime_generic(this), runtime_external(this); - Bind(&if_stringistwobyte); - { - var_result.Bind( - Load(MachineType::Uint16(), string, - IntPtrAdd(WordShl(index, IntPtrConstant(1)), - IntPtrConstant(SeqTwoByteString::kHeaderSize - - kHeapObjectTag)))); - Goto(&done_loop); - } - } + ToDirectStringAssembler to_direct(state(), string); + Node* const direct_string = to_direct.TryToDirect(&runtime_generic); + Node* const offset = IntPtrAdd(int_index, to_direct.offset()); + Node* const instance_type = to_direct.instance_type(); - Bind(&if_stringisnotsequential); - { - // Check if the {string} is a ConsString. - Label if_stringiscons(this), if_stringisnotcons(this); - Branch(Word32Equal(Word32And(string_instance_type, - Int32Constant(kStringRepresentationMask)), - Int32Constant(kConsStringTag)), - &if_stringiscons, &if_stringisnotcons); - - Bind(&if_stringiscons); - { - // Check whether the right hand side is the empty string (i.e. if - // this is really a flat string in a cons string). If that is not - // the case we flatten the string first. - Label if_rhsisempty(this), if_rhsisnotempty(this, Label::kDeferred); - Node* rhs = LoadObjectField(string, ConsString::kSecondOffset); - Branch(WordEqual(rhs, EmptyStringConstant()), &if_rhsisempty, - &if_rhsisnotempty); - - Bind(&if_rhsisempty); - { - // Just operate on the left hand side of the {string}. - var_string.Bind(LoadObjectField(string, ConsString::kFirstOffset)); - Goto(&loop); - } + Node* const string_data = to_direct.PointerToData(&runtime_external); - Bind(&if_rhsisnotempty); - { - // Flatten the {string} and lookup in the resulting string. - var_string.Bind(CallRuntime(Runtime::kFlattenString, - NoContextConstant(), string)); - Goto(&loop); - } - } + // Check if the {string} is a TwoByteSeqString or a OneByteSeqString. + Label if_stringistwobyte(this), if_stringisonebyte(this); + Branch(IsOneByteStringInstanceType(instance_type), &if_stringisonebyte, + &if_stringistwobyte); - Bind(&if_stringisnotcons); - { - // Check if the {string} is an ExternalString. - Label if_stringisexternal(this), if_stringisnotexternal(this); - Branch(Word32Equal(Word32And(string_instance_type, - Int32Constant(kStringRepresentationMask)), - Int32Constant(kExternalStringTag)), - &if_stringisexternal, &if_stringisnotexternal); - - Bind(&if_stringisexternal); - { - // Check if the {string} is a short external string. - Label if_stringisnotshort(this), - if_stringisshort(this, Label::kDeferred); - Branch(Word32Equal(Word32And(string_instance_type, - Int32Constant(kShortExternalStringMask)), - Int32Constant(0)), - &if_stringisnotshort, &if_stringisshort); - - Bind(&if_stringisnotshort); - { - // Load the actual resource data from the {string}. - Node* string_resource_data = - LoadObjectField(string, ExternalString::kResourceDataOffset, - MachineType::Pointer()); - - // Check if the {string} is a TwoByteExternalString or a - // OneByteExternalString. - Label if_stringistwobyte(this), if_stringisonebyte(this); - Branch(Word32Equal(Word32And(string_instance_type, - Int32Constant(kStringEncodingMask)), - Int32Constant(kTwoByteStringTag)), - &if_stringistwobyte, &if_stringisonebyte); - - Bind(&if_stringisonebyte); - { - var_result.Bind( - Load(MachineType::Uint8(), string_resource_data, index)); - Goto(&done_loop); - } + BIND(&if_stringisonebyte); + { + var_result.Bind(Load(MachineType::Uint8(), string_data, offset)); + Goto(&out); + } - Bind(&if_stringistwobyte); - { - var_result.Bind(Load(MachineType::Uint16(), string_resource_data, - WordShl(index, IntPtrConstant(1)))); - Goto(&done_loop); - } - } + BIND(&if_stringistwobyte); + { + var_result.Bind(Load(MachineType::Uint16(), string_data, + WordShl(offset, IntPtrConstant(1)))); + Goto(&out); + } - Bind(&if_stringisshort); - { - // The {string} might be compressed, call the runtime. - var_result.Bind(SmiToWord32( - CallRuntime(Runtime::kExternalStringGetChar, - NoContextConstant(), string, SmiTag(index)))); - Goto(&done_loop); - } - } + BIND(&runtime_generic); + { + Node* const smi_index = ParameterToTagged(index, parameter_mode); + Node* const result = CallRuntime(Runtime::kStringCharCodeAtRT, + NoContextConstant(), string, smi_index); + var_result.Bind(SmiToWord32(result)); + Goto(&out); + } - Bind(&if_stringisnotexternal); - { - Label if_stringissliced(this), if_stringisthin(this); - Branch( - Word32Equal(Word32And(string_instance_type, - Int32Constant(kStringRepresentationMask)), - Int32Constant(kSlicedStringTag)), - &if_stringissliced, &if_stringisthin); - Bind(&if_stringissliced); - { - // The {string} is a SlicedString, continue with its parent. - Node* string_offset = - LoadAndUntagObjectField(string, SlicedString::kOffsetOffset); - Node* string_parent = - LoadObjectField(string, SlicedString::kParentOffset); - var_index.Bind(IntPtrAdd(index, string_offset)); - var_string.Bind(string_parent); - Goto(&loop); - } - Bind(&if_stringisthin); - { - // The {string} is a ThinString, continue with its actual value. - var_string.Bind(LoadObjectField(string, ThinString::kActualOffset)); - Goto(&loop); - } - } - } - } + BIND(&runtime_external); + { + Node* const result = + CallRuntime(Runtime::kExternalStringGetChar, NoContextConstant(), + direct_string, SmiTag(offset)); + var_result.Bind(SmiToWord32(result)); + Goto(&out); } - Bind(&done_loop); + BIND(&out); return var_result.value(); } Node* CodeStubAssembler::StringFromCharCode(Node* code) { - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); // Check if the {code} is a one-byte char code. Label if_codeisonebyte(this), if_codeistwobyte(this, Label::kDeferred), if_done(this); Branch(Int32LessThanOrEqual(code, Int32Constant(String::kMaxOneByteCharCode)), &if_codeisonebyte, &if_codeistwobyte); - Bind(&if_codeisonebyte); + BIND(&if_codeisonebyte); { // Load the isolate wide single character string cache. Node* cache = LoadRoot(Heap::kSingleCharacterStringCacheRootIndex); @@ -3191,7 +3263,7 @@ Node* CodeStubAssembler::StringFromCharCode(Node* code) { Branch(WordEqual(entry, UndefinedConstant()), &if_entryisundefined, &if_entryisnotundefined); - Bind(&if_entryisundefined); + BIND(&if_entryisundefined); { // Allocate a new SeqOneByteString for {code} and store it in the {cache}. Node* result = AllocateSeqOneByteString(1); @@ -3203,7 +3275,7 @@ Node* CodeStubAssembler::StringFromCharCode(Node* code) { Goto(&if_done); } - Bind(&if_entryisnotundefined); + BIND(&if_entryisnotundefined); { // Return the entry from the {cache}. var_result.Bind(entry); @@ -3211,7 +3283,7 @@ Node* CodeStubAssembler::StringFromCharCode(Node* code) { } } - Bind(&if_codeistwobyte); + BIND(&if_codeistwobyte); { // Allocate a new SeqTwoByteString for {code}. Node* result = AllocateSeqTwoByteString(1); @@ -3222,7 +3294,7 @@ Node* CodeStubAssembler::StringFromCharCode(Node* code) { Goto(&if_done); } - Bind(&if_done); + BIND(&if_done); return var_result.value(); } @@ -3240,18 +3312,16 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Variable Variable; - Label end(a), two_byte_sequential(a); + Label end(a), one_byte_sequential(a), two_byte_sequential(a); Variable var_result(a, MachineRepresentation::kTagged); Node* const smi_zero = a->SmiConstant(Smi::kZero); - STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); - a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, - a->Int32Constant(kStringEncodingMask)), - a->Int32Constant(0)), - &two_byte_sequential); + a->Branch(a->IsOneByteStringInstanceType(from_instance_type), + &one_byte_sequential, &two_byte_sequential); // The subject string is a sequential one-byte string. + a->BIND(&one_byte_sequential); { Node* result = a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); @@ -3265,7 +3335,7 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, } // The subject string is a sequential two-byte string. - a->Bind(&two_byte_sequential); + a->BIND(&two_byte_sequential); { Node* result = a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); @@ -3278,7 +3348,7 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, a->Goto(&end); } - a->Bind(&end); + a->BIND(&end); return var_result.value(); } @@ -3286,27 +3356,14 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, Node* to) { - Label end(this); - Label runtime(this); - - Node* const int_zero = Int32Constant(0); - - // Int32 variables. - Variable var_instance_type(this, MachineRepresentation::kWord32, int_zero); - Variable var_representation(this, MachineRepresentation::kWord32, int_zero); - - Variable var_from(this, MachineRepresentation::kTagged, from); // Smi. - Variable var_string(this, MachineRepresentation::kTagged, string); // String. - Variable var_result(this, MachineRepresentation::kTagged); // String. + VARIABLE(var_result, MachineRepresentation::kTagged); + ToDirectStringAssembler to_direct(state(), string); + Label end(this), runtime(this); // Make sure first argument is a string. CSA_ASSERT(this, TaggedIsNotSmi(string)); CSA_ASSERT(this, IsString(string)); - // Load the instance type of the {string}. - Node* const instance_type = LoadInstanceType(string); - var_instance_type.Bind(instance_type); - // Make sure that both from and to are non-negative smis. GotoIfNot(TaggedIsPositiveSmi(from), &runtime); @@ -3329,132 +3386,56 @@ Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, // TODO(jgruber): Add an additional case for substring of length == 0? // Deal with different string types: update the index if necessary - // and put the underlying string into var_string. - - // If the string is not indirect, it can only be sequential or external. - STATIC_ASSERT(kIsIndirectStringMask == - (kSlicedStringTag & kConsStringTag & kThinStringTag)); - STATIC_ASSERT(kIsIndirectStringMask != 0); - Label underlying_unpacked(this); - GotoIf(Word32Equal( - Word32And(instance_type, Int32Constant(kIsIndirectStringMask)), - Int32Constant(0)), - &underlying_unpacked); - - // The subject string is a sliced, cons, or thin string. - - Label thin_string(this), thin_or_sliced(this); - var_representation.Bind( - Word32And(instance_type, Int32Constant(kStringRepresentationMask))); - GotoIf( - Word32NotEqual(var_representation.value(), Int32Constant(kConsStringTag)), - &thin_or_sliced); - - // Cons string. Check whether it is flat, then fetch first part. - // Flat cons strings have an empty second part. - { - GotoIf(WordNotEqual(LoadObjectField(string, ConsString::kSecondOffset), - EmptyStringConstant()), - &runtime); - - Node* first_string_part = LoadObjectField(string, ConsString::kFirstOffset); - var_string.Bind(first_string_part); - var_instance_type.Bind(LoadInstanceType(first_string_part)); - var_representation.Bind(Word32And( - var_instance_type.value(), Int32Constant(kStringRepresentationMask))); - - // The loaded first part might be a thin string. - Branch(Word32Equal(Word32And(var_instance_type.value(), - Int32Constant(kIsIndirectStringMask)), - Int32Constant(0)), - &underlying_unpacked, &thin_string); - } - - Bind(&thin_or_sliced); - { - GotoIf( - Word32Equal(var_representation.value(), Int32Constant(kThinStringTag)), - &thin_string); - // Otherwise it's a sliced string. - // Fetch parent and correct start index by offset. - Node* sliced_offset = - LoadObjectField(var_string.value(), SlicedString::kOffsetOffset); - var_from.Bind(SmiAdd(from, sliced_offset)); + // and extract the underlying string. - Node* slice_parent = LoadObjectField(string, SlicedString::kParentOffset); - var_string.Bind(slice_parent); - - Node* slice_parent_instance_type = LoadInstanceType(slice_parent); - var_instance_type.Bind(slice_parent_instance_type); - - // The loaded parent might be a thin string. - Branch(Word32Equal(Word32And(var_instance_type.value(), - Int32Constant(kIsIndirectStringMask)), - Int32Constant(0)), - &underlying_unpacked, &thin_string); - } - - Bind(&thin_string); - { - Node* actual_string = - LoadObjectField(var_string.value(), ThinString::kActualOffset); - var_string.Bind(actual_string); - var_instance_type.Bind(LoadInstanceType(actual_string)); - Goto(&underlying_unpacked); - } + Node* const direct_string = to_direct.TryToDirect(&runtime); + Node* const offset = SmiAdd(from, SmiTag(to_direct.offset())); + Node* const instance_type = to_direct.instance_type(); // The subject string can only be external or sequential string of either // encoding at this point. Label external_string(this); - Bind(&underlying_unpacked); { if (FLAG_string_slices) { - Label copy_routine(this); + Label next(this); // Short slice. Copy instead of slicing. GotoIf(SmiLessThan(substr_length, SmiConstant(Smi::FromInt(SlicedString::kMinLength))), - ©_routine); + &next); // Allocate new sliced string. - Label two_byte_slice(this); - STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); - STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); - Counters* counters = isolate()->counters(); IncrementCounter(counters->sub_string_native(), 1); - GotoIf(Word32Equal(Word32And(var_instance_type.value(), - Int32Constant(kStringEncodingMask)), - Int32Constant(0)), - &two_byte_slice); - - var_result.Bind(AllocateSlicedOneByteString( - substr_length, var_string.value(), var_from.value())); - Goto(&end); + Label one_byte_slice(this), two_byte_slice(this); + Branch(IsOneByteStringInstanceType(to_direct.instance_type()), + &one_byte_slice, &two_byte_slice); - Bind(&two_byte_slice); + BIND(&one_byte_slice); + { + var_result.Bind( + AllocateSlicedOneByteString(substr_length, direct_string, offset)); + Goto(&end); + } - var_result.Bind(AllocateSlicedTwoByteString( - substr_length, var_string.value(), var_from.value())); - Goto(&end); + BIND(&two_byte_slice); + { + var_result.Bind( + AllocateSlicedTwoByteString(substr_length, direct_string, offset)); + Goto(&end); + } - Bind(©_routine); + BIND(&next); } // The subject string can only be external or sequential string of either // encoding at this point. - STATIC_ASSERT(kExternalStringTag != 0); - STATIC_ASSERT(kSeqStringTag == 0); - GotoIfNot(Word32Equal(Word32And(var_instance_type.value(), - Int32Constant(kExternalStringTag)), - Int32Constant(0)), - &external_string); + GotoIf(to_direct.is_external(), &external_string); var_result.Bind(AllocAndCopyStringCharacters( - this, context, var_string.value(), var_instance_type.value(), - var_from.value(), substr_length)); + this, context, direct_string, instance_type, offset, substr_length)); Counters* counters = isolate()->counters(); IncrementCounter(counters->sub_string_native(), 1); @@ -3463,14 +3444,13 @@ Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, } // Handle external string. - Bind(&external_string); + BIND(&external_string); { - Node* const fake_sequential_string = TryDerefExternalString( - var_string.value(), var_instance_type.value(), &runtime); + Node* const fake_sequential_string = to_direct.PointerToString(&runtime); - var_result.Bind(AllocAndCopyStringCharacters( - this, context, fake_sequential_string, var_instance_type.value(), - var_from.value(), substr_length)); + var_result.Bind( + AllocAndCopyStringCharacters(this, context, fake_sequential_string, + instance_type, offset, substr_length)); Counters* counters = isolate()->counters(); IncrementCounter(counters->sub_string_native(), 1); @@ -3479,14 +3459,14 @@ Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, } // Substrings of length 1 are generated through CharCodeAt and FromCharCode. - Bind(&single_char); + BIND(&single_char); { - Node* char_code = StringCharCodeAt(var_string.value(), var_from.value()); + Node* char_code = StringCharCodeAt(string, from); var_result.Bind(StringFromCharCode(char_code)); Goto(&end); } - Bind(&original_string_or_invalid_length); + BIND(&original_string_or_invalid_length); { // Longer than original string's length or negative: unsafe arguments. GotoIf(SmiAbove(substr_length, string_length), &runtime); @@ -3504,46 +3484,163 @@ Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, } // Fall back to a runtime call. - Bind(&runtime); + BIND(&runtime); { var_result.Bind( CallRuntime(Runtime::kSubString, context, string, from, to)); Goto(&end); } - Bind(&end); + BIND(&end); return var_result.value(); } -namespace { +ToDirectStringAssembler::ToDirectStringAssembler( + compiler::CodeAssemblerState* state, Node* string) + : CodeStubAssembler(state), + var_string_(this, MachineRepresentation::kTagged, string), + var_instance_type_(this, MachineRepresentation::kWord32), + var_offset_(this, MachineType::PointerRepresentation()), + var_is_external_(this, MachineRepresentation::kWord32) { + CSA_ASSERT(this, TaggedIsNotSmi(string)); + CSA_ASSERT(this, IsString(string)); -Node* IsExternalStringInstanceType(CodeStubAssembler* a, - Node* const instance_type) { - CSA_ASSERT(a, a->IsStringInstanceType(instance_type)); - return a->Word32Equal( - a->Word32And(instance_type, a->Int32Constant(kStringRepresentationMask)), - a->Int32Constant(kExternalStringTag)); + var_string_.Bind(string); + var_offset_.Bind(IntPtrConstant(0)); + var_instance_type_.Bind(LoadInstanceType(string)); + var_is_external_.Bind(Int32Constant(0)); } -Node* IsShortExternalStringInstanceType(CodeStubAssembler* a, - Node* const instance_type) { - CSA_ASSERT(a, a->IsStringInstanceType(instance_type)); - STATIC_ASSERT(kShortExternalStringTag != 0); - return a->Word32NotEqual( - a->Word32And(instance_type, a->Int32Constant(kShortExternalStringMask)), - a->Int32Constant(0)); +Node* ToDirectStringAssembler::TryToDirect(Label* if_bailout) { + VariableList vars({&var_string_, &var_offset_, &var_instance_type_}, zone()); + Label dispatch(this, vars); + Label if_iscons(this); + Label if_isexternal(this); + Label if_issliced(this); + Label if_isthin(this); + Label out(this); + + Branch(IsSequentialStringInstanceType(var_instance_type_.value()), &out, + &dispatch); + + // Dispatch based on string representation. + BIND(&dispatch); + { + int32_t values[] = { + kSeqStringTag, kConsStringTag, kExternalStringTag, + kSlicedStringTag, kThinStringTag, + }; + Label* labels[] = { + &out, &if_iscons, &if_isexternal, &if_issliced, &if_isthin, + }; + STATIC_ASSERT(arraysize(values) == arraysize(labels)); + + Node* const representation = Word32And( + var_instance_type_.value(), Int32Constant(kStringRepresentationMask)); + Switch(representation, if_bailout, values, labels, arraysize(values)); + } + + // Cons string. Check whether it is flat, then fetch first part. + // Flat cons strings have an empty second part. + BIND(&if_iscons); + { + Node* const string = var_string_.value(); + GotoIfNot(IsEmptyString(LoadObjectField(string, ConsString::kSecondOffset)), + if_bailout); + + Node* const lhs = LoadObjectField(string, ConsString::kFirstOffset); + var_string_.Bind(lhs); + var_instance_type_.Bind(LoadInstanceType(lhs)); + + Goto(&dispatch); + } + + // Sliced string. Fetch parent and correct start index by offset. + BIND(&if_issliced); + { + Node* const string = var_string_.value(); + Node* const sliced_offset = + LoadAndUntagObjectField(string, SlicedString::kOffsetOffset); + var_offset_.Bind(IntPtrAdd(var_offset_.value(), sliced_offset)); + + Node* const parent = LoadObjectField(string, SlicedString::kParentOffset); + var_string_.Bind(parent); + var_instance_type_.Bind(LoadInstanceType(parent)); + + Goto(&dispatch); + } + + // Thin string. Fetch the actual string. + BIND(&if_isthin); + { + Node* const string = var_string_.value(); + Node* const actual_string = + LoadObjectField(string, ThinString::kActualOffset); + Node* const actual_instance_type = LoadInstanceType(actual_string); + + var_string_.Bind(actual_string); + var_instance_type_.Bind(actual_instance_type); + + Goto(&dispatch); + } + + // External string. + BIND(&if_isexternal); + var_is_external_.Bind(Int32Constant(1)); + Goto(&out); + + BIND(&out); + return var_string_.value(); } -} // namespace +Node* ToDirectStringAssembler::TryToSequential(StringPointerKind ptr_kind, + Label* if_bailout) { + CHECK(ptr_kind == PTR_TO_DATA || ptr_kind == PTR_TO_STRING); + + VARIABLE(var_result, MachineType::PointerRepresentation()); + Label out(this), if_issequential(this), if_isexternal(this, Label::kDeferred); + Branch(is_external(), &if_isexternal, &if_issequential); + + BIND(&if_issequential); + { + STATIC_ASSERT(SeqOneByteString::kHeaderSize == + SeqTwoByteString::kHeaderSize); + Node* result = BitcastTaggedToWord(var_string_.value()); + if (ptr_kind == PTR_TO_DATA) { + result = IntPtrAdd(result, IntPtrConstant(SeqOneByteString::kHeaderSize - + kHeapObjectTag)); + } + var_result.Bind(result); + Goto(&out); + } + + BIND(&if_isexternal); + { + GotoIf(IsShortExternalStringInstanceType(var_instance_type_.value()), + if_bailout); + + Node* const string = var_string_.value(); + Node* result = LoadObjectField(string, ExternalString::kResourceDataOffset, + MachineType::Pointer()); + if (ptr_kind == PTR_TO_STRING) { + result = IntPtrSub(result, IntPtrConstant(SeqOneByteString::kHeaderSize - + kHeapObjectTag)); + } + var_result.Bind(result); + Goto(&out); + } + + BIND(&out); + return var_result.value(); +} Node* CodeStubAssembler::TryDerefExternalString(Node* const string, Node* const instance_type, Label* if_bailout) { Label out(this); - USE(IsExternalStringInstanceType); - CSA_ASSERT(this, IsExternalStringInstanceType(this, instance_type)); - GotoIf(IsShortExternalStringInstanceType(this, instance_type), if_bailout); + CSA_ASSERT(this, IsExternalStringInstanceType(instance_type)); + GotoIf(IsShortExternalStringInstanceType(instance_type), if_bailout); // Move the pointer so that offset-wise, it looks like a sequential string. STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); @@ -3570,14 +3667,14 @@ void CodeStubAssembler::MaybeDerefIndirectString(Variable* var_string, GotoIf(WordEqual(rhs, EmptyStringConstant()), &deref); Goto(&done); - Bind(&deref); + BIND(&deref); STATIC_ASSERT(ThinString::kActualOffset == ConsString::kFirstOffset); var_string->Bind( LoadObjectField(var_string->value(), ThinString::kActualOffset)); var_did_something->Bind(IntPtrConstant(1)); Goto(&done); - Bind(&done); + BIND(&done); } void CodeStubAssembler::MaybeDerefIndirectStrings(Variable* var_left, @@ -3585,8 +3682,8 @@ void CodeStubAssembler::MaybeDerefIndirectStrings(Variable* var_left, Variable* var_right, Node* right_instance_type, Label* did_something) { - Variable var_did_something(this, MachineType::PointerRepresentation(), - IntPtrConstant(0)); + VARIABLE(var_did_something, MachineType::PointerRepresentation(), + IntPtrConstant(0)); MaybeDerefIndirectString(var_left, left_instance_type, &var_did_something); MaybeDerefIndirectString(var_right, right_instance_type, &var_did_something); @@ -3597,12 +3694,9 @@ void CodeStubAssembler::MaybeDerefIndirectStrings(Variable* var_left, Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, AllocationFlags flags) { - Label check_right(this); - Label runtime(this, Label::kDeferred); - Label cons(this); - Variable result(this, MachineRepresentation::kTagged); - Label done(this, &result); - Label done_native(this, &result); + VARIABLE(result, MachineRepresentation::kTagged); + Label check_right(this), runtime(this, Label::kDeferred), cons(this), + done(this, &result), done_native(this, &result); Counters* counters = isolate()->counters(); Node* left_length = LoadStringLength(left); @@ -3610,13 +3704,13 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, result.Bind(right); Goto(&done_native); - Bind(&check_right); + BIND(&check_right); Node* right_length = LoadStringLength(right); GotoIf(WordNotEqual(IntPtrConstant(0), right_length), &cons); result.Bind(left); Goto(&done_native); - Bind(&cons); + BIND(&cons); { CSA_ASSERT(this, TaggedIsSmi(left_length)); CSA_ASSERT(this, TaggedIsSmi(right_length)); @@ -3624,8 +3718,8 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, GotoIf(SmiAboveOrEqual(new_length, SmiConstant(String::kMaxLength)), &runtime); - Variable var_left(this, MachineRepresentation::kTagged, left); - Variable var_right(this, MachineRepresentation::kTagged, right); + VARIABLE(var_left, MachineRepresentation::kTagged, left); + VARIABLE(var_right, MachineRepresentation::kTagged, right); Variable* input_vars[2] = {&var_left, &var_right}; Label non_cons(this, 2, input_vars); Label slow(this, Label::kDeferred); @@ -3636,7 +3730,7 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, var_right.value(), flags)); Goto(&done_native); - Bind(&non_cons); + BIND(&non_cons); Comment("Full string concatenate"); Node* left_instance_type = LoadInstanceType(var_left.value()); @@ -3676,7 +3770,7 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, result.Bind(new_string); Goto(&done_native); - Bind(&two_byte); + BIND(&two_byte); { // Two-byte sequential string case new_string = @@ -3693,7 +3787,7 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, Goto(&done_native); } - Bind(&slow); + BIND(&slow); { // Try to unwrap indirect strings, restart the above attempt on success. MaybeDerefIndirectStrings(&var_left, left_instance_type, &var_right, @@ -3701,39 +3795,38 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, Goto(&runtime); } } - Bind(&runtime); + BIND(&runtime); { result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right)); Goto(&done); } - Bind(&done_native); + BIND(&done_native); { IncrementCounter(counters->string_add_native(), 1); Goto(&done); } - Bind(&done); + BIND(&done); return result.value(); } Node* CodeStubAssembler::StringFromCodePoint(Node* codepoint, UnicodeEncoding encoding) { - Variable var_result(this, MachineRepresentation::kTagged, - EmptyStringConstant()); + VARIABLE(var_result, MachineRepresentation::kTagged, EmptyStringConstant()); Label if_isword16(this), if_isword32(this), return_result(this); Branch(Uint32LessThan(codepoint, Int32Constant(0x10000)), &if_isword16, &if_isword32); - Bind(&if_isword16); + BIND(&if_isword16); { var_result.Bind(StringFromCharCode(codepoint)); Goto(&return_result); } - Bind(&if_isword32); + BIND(&if_isword32); { switch (encoding) { case UnicodeEncoding::UTF16: @@ -3765,7 +3858,7 @@ Node* CodeStubAssembler::StringFromCodePoint(Node* codepoint, Goto(&return_result); } - Bind(&return_result); + BIND(&return_result); return var_result.value(); } @@ -3773,7 +3866,7 @@ Node* CodeStubAssembler::StringToNumber(Node* context, Node* input) { Label runtime(this, Label::kDeferred); Label end(this); - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); // Check if string has a cached array index. Node* hash = LoadNameHashField(input); @@ -3785,21 +3878,19 @@ Node* CodeStubAssembler::StringToNumber(Node* context, Node* input) { SmiTag(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash))); Goto(&end); - Bind(&runtime); + BIND(&runtime); { var_result.Bind(CallRuntime(Runtime::kStringToNumber, context, input)); Goto(&end); } - Bind(&end); + BIND(&end); return var_result.value(); } Node* CodeStubAssembler::NumberToString(Node* context, Node* argument) { - Variable result(this, MachineRepresentation::kTagged); - Label runtime(this, Label::kDeferred); - Label smi(this); - Label done(this, &result); + VARIABLE(result, MachineRepresentation::kTagged); + Label runtime(this, Label::kDeferred), smi(this), done(this, &result); // Load the number string cache. Node* number_string_cache = LoadRoot(Heap::kNumberStringCacheRootIndex); @@ -3847,14 +3938,14 @@ Node* CodeStubAssembler::NumberToString(Node* context, Node* argument) { result.Bind(LoadFixedArrayElement(number_string_cache, index, kPointerSize)); Goto(&done); - Bind(&runtime); + BIND(&runtime); { // No cache entry, go to the runtime. result.Bind(CallRuntime(Runtime::kNumberToString, context, argument)); } Goto(&done); - Bind(&smi); + BIND(&smi); { // Load the smi key, make sure it matches the smi we're looking for. Node* smi_index = BitcastWordToTagged( @@ -3870,13 +3961,13 @@ Node* CodeStubAssembler::NumberToString(Node* context, Node* argument) { Goto(&done); } - Bind(&done); + BIND(&done); return result.value(); } Node* CodeStubAssembler::ToName(Node* context, Node* value) { Label end(this); - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); Label is_number(this); GotoIf(TaggedIsSmi(value), &is_number); @@ -3890,14 +3981,14 @@ Node* CodeStubAssembler::ToName(Node* context, Node* value) { var_result.Bind(value); Goto(&end); - Bind(&is_number); + BIND(&is_number); { Callable callable = CodeFactory::NumberToString(isolate()); var_result.Bind(CallStub(callable, context, value)); Goto(&end); } - Bind(¬_name); + BIND(¬_name); { GotoIf(Word32Equal(value_instance_type, Int32Constant(HEAP_NUMBER_TYPE)), &is_number); @@ -3909,14 +4000,14 @@ Node* CodeStubAssembler::ToName(Node* context, Node* value) { var_result.Bind(LoadObjectField(value, Oddball::kToStringOffset)); Goto(&end); - Bind(¬_oddball); + BIND(¬_oddball); { var_result.Bind(CallRuntime(Runtime::kToName, context, value)); Goto(&end); } } - Bind(&end); + BIND(&end); return var_result.value(); } @@ -3926,12 +4017,12 @@ Node* CodeStubAssembler::NonNumberToNumber(Node* context, Node* input) { CSA_ASSERT(this, Word32BinaryNot(IsHeapNumberMap(LoadMap(input)))); // We might need to loop once here due to ToPrimitive conversions. - Variable var_input(this, MachineRepresentation::kTagged, input); - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_input, MachineRepresentation::kTagged, input); + VARIABLE(var_result, MachineRepresentation::kTagged); Label loop(this, &var_input); Label end(this); Goto(&loop); - Bind(&loop); + BIND(&loop); { // Load the current {input} value (known to be a HeapObject). Node* input = var_input.value(); @@ -3947,21 +4038,21 @@ Node* CodeStubAssembler::NonNumberToNumber(Node* context, Node* input) { Branch(IsJSReceiverInstanceType(input_instance_type), &if_inputisreceiver, &if_inputisother); - Bind(&if_inputisstring); + BIND(&if_inputisstring); { // The {input} is a String, use the fast stub to convert it to a Number. var_result.Bind(StringToNumber(context, input)); Goto(&end); } - Bind(&if_inputisoddball); + BIND(&if_inputisoddball); { // The {input} is an Oddball, we just need to load the Number value of it. var_result.Bind(LoadObjectField(input, Oddball::kToNumberOffset)); Goto(&end); } - Bind(&if_inputisreceiver); + BIND(&if_inputisreceiver); { // The {input} is a JSReceiver, we need to convert it to a Primitive first // using the ToPrimitive type conversion, preferably yielding a Number. @@ -3976,14 +4067,14 @@ Node* CodeStubAssembler::NonNumberToNumber(Node* context, Node* input) { Branch(IsHeapNumberMap(result_map), &if_resultisnumber, &if_resultisnotnumber); - Bind(&if_resultisnumber); + BIND(&if_resultisnumber); { // The ToPrimitive conversion already gave us a Number, so we're done. var_result.Bind(result); Goto(&end); } - Bind(&if_resultisnotnumber); + BIND(&if_resultisnotnumber); { // We now have a Primitive {result}, but it's not yet a Number. var_input.Bind(result); @@ -3991,7 +4082,7 @@ Node* CodeStubAssembler::NonNumberToNumber(Node* context, Node* input) { } } - Bind(&if_inputisother); + BIND(&if_inputisother); { // The {input} is something else (e.g. Symbol), let the runtime figure // out the correct exception. @@ -4004,12 +4095,12 @@ Node* CodeStubAssembler::NonNumberToNumber(Node* context, Node* input) { } } - Bind(&end); + BIND(&end); return var_result.value(); } Node* CodeStubAssembler::ToNumber(Node* context, Node* input) { - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); Label end(this); Label not_smi(this, Label::kDeferred); @@ -4017,7 +4108,7 @@ Node* CodeStubAssembler::ToNumber(Node* context, Node* input) { var_result.Bind(input); Goto(&end); - Bind(¬_smi); + BIND(¬_smi); { Label not_heap_number(this, Label::kDeferred); Node* input_map = LoadMap(input); @@ -4026,24 +4117,25 @@ Node* CodeStubAssembler::ToNumber(Node* context, Node* input) { var_result.Bind(input); Goto(&end); - Bind(¬_heap_number); + BIND(¬_heap_number); { var_result.Bind(NonNumberToNumber(context, input)); Goto(&end); } } - Bind(&end); + BIND(&end); return var_result.value(); } +// ES#sec-touint32 Node* CodeStubAssembler::ToUint32(Node* context, Node* input) { Node* const float_zero = Float64Constant(0.0); Node* const float_two_32 = Float64Constant(static_cast<double>(1ULL << 32)); Label out(this); - Variable var_result(this, MachineRepresentation::kTagged, input); + VARIABLE(var_result, MachineRepresentation::kTagged, input); // Early exit for positive smis. { @@ -4051,7 +4143,7 @@ Node* CodeStubAssembler::ToUint32(Node* context, Node* input) { // have a ToNumber with multiple exits. Label next(this, Label::kDeferred); Branch(TaggedIsPositiveSmi(input), &out, &next); - Bind(&next); + BIND(&next); } Node* const number = ToNumber(context, input); @@ -4061,23 +4153,21 @@ Node* CodeStubAssembler::ToUint32(Node* context, Node* input) { { Label next(this, Label::kDeferred); Branch(TaggedIsPositiveSmi(number), &out, &next); - Bind(&next); + BIND(&next); } Label if_isnegativesmi(this), if_isheapnumber(this); Branch(TaggedIsSmi(number), &if_isnegativesmi, &if_isheapnumber); - Bind(&if_isnegativesmi); + BIND(&if_isnegativesmi); { - // floor({input}) mod 2^32 === {input} + 2^32. - Node* const float_number = SmiToFloat64(number); - Node* const float_result = Float64Add(float_number, float_two_32); - Node* const result = ChangeFloat64ToTagged(float_result); - var_result.Bind(result); + Node* const uint32_value = SmiToWord32(number); + Node* float64_value = ChangeUint32ToFloat64(uint32_value); + var_result.Bind(AllocateHeapNumberWithValue(float64_value)); Goto(&out); } - Bind(&if_isheapnumber); + BIND(&if_isheapnumber); { Label return_zero(this); Node* const value = LoadHeapNumberValue(number); @@ -4086,14 +4176,14 @@ Node* CodeStubAssembler::ToUint32(Node* context, Node* input) { // +-0. Label next(this); Branch(Float64Equal(value, float_zero), &return_zero, &next); - Bind(&next); + BIND(&next); } { // NaN. Label next(this); Branch(Float64Equal(value, value), &next, &return_zero); - Bind(&next); + BIND(&next); } { @@ -4102,7 +4192,7 @@ Node* CodeStubAssembler::ToUint32(Node* context, Node* input) { Node* const positive_infinity = Float64Constant(std::numeric_limits<double>::infinity()); Branch(Float64Equal(value, positive_infinity), &return_zero, &next); - Bind(&next); + BIND(&next); } { @@ -4111,13 +4201,15 @@ Node* CodeStubAssembler::ToUint32(Node* context, Node* input) { Node* const negative_infinity = Float64Constant(-1.0 * std::numeric_limits<double>::infinity()); Branch(Float64Equal(value, negative_infinity), &return_zero, &next); - Bind(&next); + BIND(&next); } - // Return floor({input}) mod 2^32 (assuming mod semantics that always return - // positive results). + // * Let int be the mathematical value that is the same sign as number and + // whose magnitude is floor(abs(number)). + // * Let int32bit be int modulo 2^32. + // * Return int32bit. { - Node* x = Float64Floor(value); + Node* x = Float64Trunc(value); x = Float64Mod(x, float_two_32); x = Float64Add(x, float_two_32); x = Float64Mod(x, float_two_32); @@ -4127,21 +4219,21 @@ Node* CodeStubAssembler::ToUint32(Node* context, Node* input) { Goto(&out); } - Bind(&return_zero); + BIND(&return_zero); { var_result.Bind(SmiConstant(Smi::kZero)); Goto(&out); } } - Bind(&out); + BIND(&out); return var_result.value(); } Node* CodeStubAssembler::ToString(Node* context, Node* input) { Label is_number(this); Label runtime(this, Label::kDeferred); - Variable result(this, MachineRepresentation::kTagged); + VARIABLE(result, MachineRepresentation::kTagged); Label done(this, &result); GotoIf(TaggedIsSmi(input), &is_number); @@ -4155,11 +4247,11 @@ Node* CodeStubAssembler::ToString(Node* context, Node* input) { Label not_heap_number(this); Branch(IsHeapNumberMap(input_map), &is_number, ¬_heap_number); - Bind(&is_number); + BIND(&is_number); result.Bind(NumberToString(context, input)); Goto(&done); - Bind(¬_heap_number); + BIND(¬_heap_number); { GotoIf(Word32NotEqual(input_instance_type, Int32Constant(ODDBALL_TYPE)), &runtime); @@ -4167,24 +4259,24 @@ Node* CodeStubAssembler::ToString(Node* context, Node* input) { Goto(&done); } - Bind(&runtime); + BIND(&runtime); { result.Bind(CallRuntime(Runtime::kToString, context, input)); Goto(&done); } - Bind(&done); + BIND(&done); return result.value(); } Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) { Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this); - Variable result(this, MachineRepresentation::kTagged); + VARIABLE(result, MachineRepresentation::kTagged); Label done(this, &result); BranchIfJSReceiver(input, &if_isreceiver, &if_isnotreceiver); - Bind(&if_isreceiver); + BIND(&if_isreceiver); { // Convert {input} to a primitive first passing Number hint. Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate()); @@ -4192,23 +4284,75 @@ Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) { Goto(&done); } - Bind(&if_isnotreceiver); + BIND(&if_isnotreceiver); { result.Bind(input); Goto(&done); } - Bind(&done); + BIND(&done); + return result.value(); +} + +Node* CodeStubAssembler::ToSmiIndex(Node* const input, Node* const context, + Label* range_error) { + VARIABLE(result, MachineRepresentation::kTagged, input); + Label check_undefined(this), return_zero(this), defined(this), + negative_check(this), done(this); + Branch(TaggedIsSmi(result.value()), &negative_check, &check_undefined); + + BIND(&check_undefined); + Branch(IsUndefined(result.value()), &return_zero, &defined); + + BIND(&defined); + result.Bind(ToInteger(context, result.value(), + CodeStubAssembler::kTruncateMinusZero)); + GotoIfNot(TaggedIsSmi(result.value()), range_error); + CSA_ASSERT(this, TaggedIsSmi(result.value())); + Goto(&negative_check); + + BIND(&negative_check); + Branch(SmiLessThan(result.value(), SmiConstant(0)), range_error, &done); + + BIND(&return_zero); + result.Bind(SmiConstant(0)); + Goto(&done); + + BIND(&done); + return result.value(); +} + +Node* CodeStubAssembler::ToSmiLength(Node* input, Node* const context, + Label* range_error) { + VARIABLE(result, MachineRepresentation::kTagged, input); + Label to_integer(this), negative_check(this), return_zero(this), done(this); + Branch(TaggedIsSmi(result.value()), &negative_check, &to_integer); + + BIND(&to_integer); + result.Bind(ToInteger(context, result.value(), + CodeStubAssembler::kTruncateMinusZero)); + GotoIfNot(TaggedIsSmi(result.value()), range_error); + CSA_ASSERT(this, TaggedIsSmi(result.value())); + Goto(&negative_check); + + BIND(&negative_check); + Branch(SmiLessThan(result.value(), SmiConstant(0)), &return_zero, &done); + + BIND(&return_zero); + result.Bind(SmiConstant(0)); + Goto(&done); + + BIND(&done); return result.value(); } Node* CodeStubAssembler::ToInteger(Node* context, Node* input, ToIntegerTruncationMode mode) { // We might need to loop once for ToNumber conversion. - Variable var_arg(this, MachineRepresentation::kTagged, input); + VARIABLE(var_arg, MachineRepresentation::kTagged, input); Label loop(this, &var_arg), out(this); Goto(&loop); - Bind(&loop); + BIND(&loop); { // Shared entry points. Label return_zero(this, Label::kDeferred); @@ -4225,7 +4369,7 @@ Node* CodeStubAssembler::ToInteger(Node* context, Node* input, Branch(IsHeapNumberMap(LoadMap(arg)), &if_argisheapnumber, &if_argisnotheapnumber); - Bind(&if_argisheapnumber); + BIND(&if_argisheapnumber); { // Load the floating-point value of {arg}. Node* arg_value = LoadHeapNumberValue(arg); @@ -4245,7 +4389,7 @@ Node* CodeStubAssembler::ToInteger(Node* context, Node* input, Goto(&out); } - Bind(&if_argisnotheapnumber); + BIND(&if_argisnotheapnumber); { // Need to convert {arg} to a Number first. Callable callable = CodeFactory::NonNumberToNumber(isolate()); @@ -4253,12 +4397,12 @@ Node* CodeStubAssembler::ToInteger(Node* context, Node* input, Goto(&loop); } - Bind(&return_zero); + BIND(&return_zero); var_arg.Bind(SmiConstant(Smi::kZero)); Goto(&out); } - Bind(&out); + BIND(&out); return var_arg.value(); } @@ -4327,7 +4471,7 @@ void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, var_index->Bind(TryToIntptr(key, &if_keyisnotindex)); Goto(if_keyisindex); - Bind(&if_keyisnotindex); + BIND(&if_keyisnotindex); Node* key_map = LoadMap(key); var_unique->Bind(key); // Symbols are unique. @@ -4359,11 +4503,11 @@ void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout); Goto(if_keyisunique); - Bind(&if_thinstring); + BIND(&if_thinstring); var_unique->Bind(LoadObjectField(key, ThinString::kActualOffset)); Goto(if_keyisunique); - Bind(&if_hascachedindex); + BIND(&if_hascachedindex); var_index->Bind(DecodeWordFromWord32<Name::ArrayIndexValueBits>(hash)); Goto(if_keyisindex); } @@ -4472,12 +4616,12 @@ void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, Node* undefined = UndefinedConstant(); Node* the_hole = mode == kFindExisting ? nullptr : TheHoleConstant(); - Variable var_count(this, MachineType::PointerRepresentation(), count); - Variable var_entry(this, MachineType::PointerRepresentation(), entry); + VARIABLE(var_count, MachineType::PointerRepresentation(), count); + VARIABLE(var_entry, MachineType::PointerRepresentation(), entry); Variable* loop_vars[] = {&var_count, &var_entry, var_name_index}; Label loop(this, 3, loop_vars); Goto(&loop); - Bind(&loop); + BIND(&loop); { Node* entry = var_entry.value(); @@ -4551,12 +4695,12 @@ void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, Node* undefined = UndefinedConstant(); Node* the_hole = TheHoleConstant(); - Variable var_count(this, MachineType::PointerRepresentation(), count); + VARIABLE(var_count, MachineType::PointerRepresentation(), count); Variable* loop_vars[] = {&var_count, var_entry}; Label loop(this, 2, loop_vars); var_entry->Bind(entry); Goto(&loop); - Bind(&loop); + BIND(&loop); { Node* entry = var_entry->value(); @@ -4567,12 +4711,12 @@ void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, { Label if_currentissmi(this), if_currentisnotsmi(this); Branch(TaggedIsSmi(current), &if_currentissmi, &if_currentisnotsmi); - Bind(&if_currentissmi); + BIND(&if_currentissmi); { Node* current_value = SmiUntag(current); Branch(WordEqual(current_value, intptr_index), if_found, &next_probe); } - Bind(&if_currentisnotsmi); + BIND(&if_currentisnotsmi); { GotoIf(WordEqual(current, the_hole), &next_probe); // Current must be the Number. @@ -4582,7 +4726,7 @@ void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, } } - Bind(&next_probe); + BIND(&next_probe); // See Dictionary::NextProbe(). Increment(var_count); entry = WordAnd(IntPtrAdd(entry, var_count.value()), mask); @@ -4604,7 +4748,7 @@ void CodeStubAssembler::FindInsertionEntry<NameDictionary>( Label done(this); NameDictionaryLookup<NameDictionary>(dictionary, key, nullptr, var_key_index, &done, 0, kFindInsertionIndex); - Bind(&done); + BIND(&done); } template <class Dictionary> @@ -4628,8 +4772,8 @@ void CodeStubAssembler::InsertEntry<NameDictionary>(Node* dictionary, enum_index = SmiShl(enum_index, PropertyDetails::DictionaryStorageField::kShift); STATIC_ASSERT(kInitialIndex == 0); - Variable var_details(this, MachineRepresentation::kTaggedSigned, - SmiOr(SmiConstant(d.AsSmi()), enum_index)); + VARIABLE(var_details, MachineRepresentation::kTaggedSigned, + SmiOr(SmiConstant(d.AsSmi()), enum_index)); // Private names must be marked non-enumerable. Label not_private(this, &var_details); @@ -4641,7 +4785,7 @@ void CodeStubAssembler::InsertEntry<NameDictionary>(Node* dictionary, SmiShl(SmiConstant(DONT_ENUM), PropertyDetails::AttributesField::kShift); var_details.Bind(SmiOr(var_details.value(), dont_enum)); Goto(¬_private); - Bind(¬_private); + BIND(¬_private); // Finally, store the details. StoreDetailsByKeyIndex<NameDictionary>(dictionary, index, @@ -4689,7 +4833,7 @@ void CodeStubAssembler::Add(Node* dictionary, Node* key, Node* value, } SetNumberOfElements<Dictionary>(dictionary, new_nof); - Variable var_key_index(this, MachineType::PointerRepresentation()); + VARIABLE(var_key_index, MachineType::PointerRepresentation()); FindInsertionEntry<Dictionary>(dictionary, key, &var_key_index); InsertEntry<Dictionary>(dictionary, key, value, var_key_index.value(), enum_index); @@ -4764,10 +4908,10 @@ void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name, Variable* var_name_index, Label* if_not_found) { Comment("DescriptorLookupBinary"); - Variable var_low(this, MachineRepresentation::kWord32, Int32Constant(0)); + VARIABLE(var_low, MachineRepresentation::kWord32, Int32Constant(0)); Node* limit = Int32Sub(DescriptorArrayNumberOfEntries(descriptors), Int32Constant(1)); - Variable var_high(this, MachineRepresentation::kWord32, limit); + VARIABLE(var_high, MachineRepresentation::kWord32, limit); Node* hash = LoadNameHashField(unique_name); CSA_ASSERT(this, Word32NotEqual(hash, Int32Constant(0))); @@ -4777,7 +4921,7 @@ void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name, Variable* loop_vars[] = {&var_high, &var_low}; Label binary_loop(this, 2, loop_vars); Goto(&binary_loop); - Bind(&binary_loop); + BIND(&binary_loop); { // mid = low + (high - low) / 2 (to avoid overflow in "(low + high) / 2"). Node* mid = @@ -4791,23 +4935,23 @@ void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name, Label mid_greater(this), mid_less(this), merge(this); Branch(Uint32GreaterThanOrEqual(mid_hash, hash), &mid_greater, &mid_less); - Bind(&mid_greater); + BIND(&mid_greater); { var_high.Bind(mid); Goto(&merge); } - Bind(&mid_less); + BIND(&mid_less); { var_low.Bind(Int32Add(mid, Int32Constant(1))); Goto(&merge); } - Bind(&merge); + BIND(&merge); GotoIf(Word32NotEqual(var_low.value(), var_high.value()), &binary_loop); } Label scan_loop(this, &var_low); Goto(&scan_loop); - Bind(&scan_loop); + BIND(&scan_loop); { GotoIf(Int32GreaterThan(var_low.value(), limit), if_not_found); @@ -4822,7 +4966,7 @@ void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name, var_name_index->Bind(DescriptorArrayToKeyIndex(sort_index)); Goto(if_found); - Bind(&next); + BIND(&next); var_low.Bind(Int32Add(var_low.value(), Int32Constant(1))); Goto(&scan_loop); } @@ -4839,12 +4983,12 @@ void CodeStubAssembler::DescriptorLookup(Node* unique_name, Node* descriptors, const int kMaxElementsForLinearSearch = 32; Branch(Int32LessThanOrEqual(nof, Int32Constant(kMaxElementsForLinearSearch)), &linear_search, &binary_search); - Bind(&linear_search); + BIND(&linear_search); { DescriptorLookupLinear(unique_name, descriptors, ChangeInt32ToIntPtr(nof), if_found, var_name_index, if_not_found); } - Bind(&binary_search); + BIND(&binary_search); { DescriptorLookupBinary(unique_name, descriptors, nof, if_found, var_name_index, if_not_found); @@ -4874,7 +5018,7 @@ void CodeStubAssembler::TryLookupProperty( Label if_isfastmap(this), if_isslowmap(this); Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap, &if_isfastmap); - Bind(&if_isfastmap); + BIND(&if_isfastmap); { Node* descriptors = LoadMapDescriptors(map); var_meta_storage->Bind(descriptors); @@ -4882,7 +5026,7 @@ void CodeStubAssembler::TryLookupProperty( DescriptorLookup(unique_name, descriptors, bit_field3, if_found_fast, var_name_index, if_not_found); } - Bind(&if_isslowmap); + BIND(&if_isslowmap); { Node* dictionary = LoadProperties(object); var_meta_storage->Bind(dictionary); @@ -4890,7 +5034,7 @@ void CodeStubAssembler::TryLookupProperty( NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict, var_name_index, if_not_found); } - Bind(&if_objectisspecial); + BIND(&if_objectisspecial); { // Handle global object here and other special objects in runtime. GotoIfNot(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)), @@ -4917,17 +5061,17 @@ void CodeStubAssembler::TryHasOwnProperty(Node* object, Node* map, Label* if_not_found, Label* if_bailout) { Comment("TryHasOwnProperty"); - Variable var_meta_storage(this, MachineRepresentation::kTagged); - Variable var_name_index(this, MachineType::PointerRepresentation()); + VARIABLE(var_meta_storage, MachineRepresentation::kTagged); + VARIABLE(var_name_index, MachineType::PointerRepresentation()); Label if_found_global(this); TryLookupProperty(object, map, instance_type, unique_name, if_found, if_found, &if_found_global, &var_meta_storage, &var_name_index, if_not_found, if_bailout); - Bind(&if_found_global); + BIND(&if_found_global); { - Variable var_value(this, MachineRepresentation::kTagged); - Variable var_details(this, MachineRepresentation::kWord32); + VARIABLE(var_value, MachineRepresentation::kTagged); + VARIABLE(var_details, MachineRepresentation::kWord32); // Check if the property cell is not deleted. LoadPropertyFromGlobalDictionary(var_meta_storage.value(), var_name_index.value(), &var_value, @@ -4954,7 +5098,7 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, Label if_in_field(this), if_in_descriptor(this), done(this); Branch(Word32Equal(location, Int32Constant(kField)), &if_in_field, &if_in_descriptor); - Bind(&if_in_field); + BIND(&if_in_field); { Node* field_index = DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details); @@ -4964,11 +5108,11 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, Node* inobject_properties = LoadMapInobjectProperties(map); Label if_inobject(this), if_backing_store(this); - Variable var_double_value(this, MachineRepresentation::kFloat64); + VARIABLE(var_double_value, MachineRepresentation::kFloat64); Label rebox_double(this, &var_double_value); Branch(UintPtrLessThan(field_index, inobject_properties), &if_inobject, &if_backing_store); - Bind(&if_inobject); + BIND(&if_inobject); { Comment("if_inobject"); Node* field_offset = @@ -4980,12 +5124,12 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, Branch(Word32NotEqual(representation, Int32Constant(Representation::kDouble)), &if_tagged, &if_double); - Bind(&if_tagged); + BIND(&if_tagged); { var_value->Bind(LoadObjectField(object, field_offset)); Goto(&done); } - Bind(&if_double); + BIND(&if_double); { if (FLAG_unbox_double_fields) { var_double_value.Bind( @@ -4997,7 +5141,7 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, Goto(&rebox_double); } } - Bind(&if_backing_store); + BIND(&if_backing_store); { Comment("if_backing_store"); Node* properties = LoadProperties(object); @@ -5008,18 +5152,18 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, Branch(Word32NotEqual(representation, Int32Constant(Representation::kDouble)), &if_tagged, &if_double); - Bind(&if_tagged); + BIND(&if_tagged); { var_value->Bind(value); Goto(&done); } - Bind(&if_double); + BIND(&if_double); { var_double_value.Bind(LoadHeapNumberValue(value)); Goto(&rebox_double); } } - Bind(&rebox_double); + BIND(&rebox_double); { Comment("rebox_double"); Node* heap_number = AllocateHeapNumberWithValue(var_double_value.value()); @@ -5027,13 +5171,13 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, Goto(&done); } } - Bind(&if_in_descriptor); + BIND(&if_in_descriptor); { var_value->Bind( LoadValueByKeyIndex<DescriptorArray>(descriptors, name_index)); Goto(&done); } - Bind(&done); + BIND(&done); Comment("] LoadPropertyFromFastObject"); } @@ -5081,7 +5225,7 @@ void CodeStubAssembler::LoadPropertyFromGlobalDictionary(Node* dictionary, Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details, Node* context, Node* receiver, Label* if_bailout) { - Variable var_value(this, MachineRepresentation::kTagged, value); + VARIABLE(var_value, MachineRepresentation::kTagged, value); Label done(this); Node* kind = DecodeWord32<PropertyDetails::KindField>(details); @@ -5093,7 +5237,7 @@ Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details, GotoIf(Word32Equal(LoadInstanceType(accessor_pair), Int32Constant(ACCESSOR_INFO_TYPE)), if_bailout); - CSA_ASSERT(this, HasInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE)); + CSA_ASSERT(this, IsAccessorPair(accessor_pair)); Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset); Node* getter_map = LoadMap(getter); Node* instance_type = LoadMapInstanceType(getter_map); @@ -5113,7 +5257,7 @@ Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details, Goto(&done); } - Bind(&done); + BIND(&done); return var_value.value(); } @@ -5124,19 +5268,19 @@ void CodeStubAssembler::TryGetOwnProperty( DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep()); Comment("TryGetOwnProperty"); - Variable var_meta_storage(this, MachineRepresentation::kTagged); - Variable var_entry(this, MachineType::PointerRepresentation()); + VARIABLE(var_meta_storage, MachineRepresentation::kTagged); + VARIABLE(var_entry, MachineType::PointerRepresentation()); Label if_found_fast(this), if_found_dict(this), if_found_global(this); - Variable var_details(this, MachineRepresentation::kWord32); + VARIABLE(var_details, MachineRepresentation::kWord32); Variable* vars[] = {var_value, &var_details}; Label if_found(this, 2, vars); TryLookupProperty(object, map, instance_type, unique_name, &if_found_fast, &if_found_dict, &if_found_global, &var_meta_storage, &var_entry, if_not_found, if_bailout); - Bind(&if_found_fast); + BIND(&if_found_fast); { Node* descriptors = var_meta_storage.value(); Node* name_index = var_entry.value(); @@ -5145,14 +5289,14 @@ void CodeStubAssembler::TryGetOwnProperty( &var_details, var_value); Goto(&if_found); } - Bind(&if_found_dict); + BIND(&if_found_dict); { Node* dictionary = var_meta_storage.value(); Node* entry = var_entry.value(); LoadPropertyFromNameDictionary(dictionary, entry, &var_details, var_value); Goto(&if_found); } - Bind(&if_found_global); + BIND(&if_found_global); { Node* dictionary = var_meta_storage.value(); Node* entry = var_entry.value(); @@ -5162,7 +5306,7 @@ void CodeStubAssembler::TryGetOwnProperty( Goto(&if_found); } // Here we have details and value which could be an accessor. - Bind(&if_found); + BIND(&if_found); { Node* value = CallGetterIfAccessor(var_value->value(), var_details.value(), context, receiver, if_bailout); @@ -5174,7 +5318,7 @@ void CodeStubAssembler::TryGetOwnProperty( void CodeStubAssembler::TryLookupElement(Node* object, Node* map, Node* instance_type, Node* intptr_index, Label* if_found, - Label* if_not_found, + Label* if_absent, Label* if_not_found, Label* if_bailout) { // Handle special objects in runtime. GotoIf(Int32LessThanOrEqual(instance_type, @@ -5185,7 +5329,8 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, // TODO(verwaest): Support other elements kinds as well. Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this), - if_isfaststringwrapper(this), if_isslowstringwrapper(this), if_oob(this); + if_isfaststringwrapper(this), if_isslowstringwrapper(this), if_oob(this), + if_typedarray(this); // clang-format off int32_t values[] = { // Handled by {if_isobjectorsmi}. @@ -5201,6 +5346,16 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, SLOW_STRING_WRAPPER_ELEMENTS, // Handled by {if_not_found}. NO_ELEMENTS, + // Handled by {if_typed_array}. + UINT8_ELEMENTS, + INT8_ELEMENTS, + UINT16_ELEMENTS, + INT16_ELEMENTS, + UINT32_ELEMENTS, + INT32_ELEMENTS, + FLOAT32_ELEMENTS, + FLOAT64_ELEMENTS, + UINT8_CLAMPED_ELEMENTS, }; Label* labels[] = { &if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi, @@ -5210,12 +5365,21 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, &if_isfaststringwrapper, &if_isslowstringwrapper, if_not_found, + &if_typedarray, + &if_typedarray, + &if_typedarray, + &if_typedarray, + &if_typedarray, + &if_typedarray, + &if_typedarray, + &if_typedarray, + &if_typedarray, }; // clang-format on STATIC_ASSERT(arraysize(values) == arraysize(labels)); Switch(elements_kind, if_bailout, values, labels, arraysize(values)); - Bind(&if_isobjectorsmi); + BIND(&if_isobjectorsmi); { Node* elements = LoadElements(object); Node* length = LoadAndUntagFixedArrayBaseLength(elements); @@ -5226,7 +5390,7 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, Node* the_hole = TheHoleConstant(); Branch(WordEqual(element, the_hole), if_not_found, if_found); } - Bind(&if_isdouble); + BIND(&if_isdouble); { Node* elements = LoadElements(object); Node* length = LoadAndUntagFixedArrayBaseLength(elements); @@ -5238,17 +5402,17 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, INTPTR_PARAMETERS, if_not_found); Goto(if_found); } - Bind(&if_isdictionary); + BIND(&if_isdictionary); { // Negative keys must be converted to property names. GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), if_bailout); - Variable var_entry(this, MachineType::PointerRepresentation()); + VARIABLE(var_entry, MachineType::PointerRepresentation()); Node* elements = LoadElements(object); NumberDictionaryLookup<SeededNumberDictionary>( elements, intptr_index, if_found, &var_entry, if_not_found); } - Bind(&if_isfaststringwrapper); + BIND(&if_isfaststringwrapper); { CSA_ASSERT(this, HasInstanceType(object, JS_VALUE_TYPE)); Node* string = LoadJSValueValue(object); @@ -5257,7 +5421,7 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found); Goto(&if_isobjectorsmi); } - Bind(&if_isslowstringwrapper); + BIND(&if_isslowstringwrapper); { CSA_ASSERT(this, HasInstanceType(object, JS_VALUE_TYPE)); Node* string = LoadJSValueValue(object); @@ -5266,7 +5430,16 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found); Goto(&if_isdictionary); } - Bind(&if_oob); + BIND(&if_typedarray); + { + Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); + GotoIf(IsDetachedBuffer(buffer), if_absent); + + Node* length = TryToIntptr( + LoadObjectField(object, JSTypedArray::kLengthOffset), if_bailout); + Branch(UintPtrLessThan(intptr_index, length), if_found, if_absent); + } + BIND(&if_oob); { // Positive OOB indices mean "not found", negative indices must be // converted to property names. @@ -5288,7 +5461,7 @@ void CodeStubAssembler::TryPrototypeChainLookup( // Ensure receiver is JSReceiver, otherwise bailout. Label if_objectisnotsmi(this); Branch(TaggedIsSmi(receiver), if_bailout, &if_objectisnotsmi); - Bind(&if_objectisnotsmi); + BIND(&if_objectisnotsmi); Node* map = LoadMap(receiver); Node* instance_type = LoadMapInstanceType(map); @@ -5299,28 +5472,28 @@ void CodeStubAssembler::TryPrototypeChainLookup( Branch( Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)), &if_objectisreceiver, if_bailout); - Bind(&if_objectisreceiver); + BIND(&if_objectisreceiver); } - Variable var_index(this, MachineType::PointerRepresentation()); - Variable var_unique(this, MachineRepresentation::kTagged); + VARIABLE(var_index, MachineType::PointerRepresentation()); + VARIABLE(var_unique, MachineRepresentation::kTagged); Label if_keyisindex(this), if_iskeyunique(this); TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, &var_unique, if_bailout); - Bind(&if_iskeyunique); + BIND(&if_iskeyunique); { - Variable var_holder(this, MachineRepresentation::kTagged, receiver); - Variable var_holder_map(this, MachineRepresentation::kTagged, map); - Variable var_holder_instance_type(this, MachineRepresentation::kWord32, - instance_type); + VARIABLE(var_holder, MachineRepresentation::kTagged, receiver); + VARIABLE(var_holder_map, MachineRepresentation::kTagged, map); + VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32, + instance_type); Variable* merged_variables[] = {&var_holder, &var_holder_map, &var_holder_instance_type}; Label loop(this, arraysize(merged_variables), merged_variables); Goto(&loop); - Bind(&loop); + BIND(&loop); { Node* holder_map = var_holder_map.value(); Node* holder_instance_type = var_holder_instance_type.value(); @@ -5329,7 +5502,7 @@ void CodeStubAssembler::TryPrototypeChainLookup( lookup_property_in_holder(receiver, var_holder.value(), holder_map, holder_instance_type, var_unique.value(), &next_proto, if_bailout); - Bind(&next_proto); + BIND(&next_proto); // Bailout if it can be an integer indexed exotic case. GotoIf( @@ -5340,7 +5513,7 @@ void CodeStubAssembler::TryPrototypeChainLookup( Label if_not_null(this); Branch(WordEqual(proto, NullConstant()), if_end, &if_not_null); - Bind(&if_not_null); + BIND(&if_not_null); Node* map = LoadMap(proto); Node* instance_type = LoadMapInstanceType(map); @@ -5351,31 +5524,31 @@ void CodeStubAssembler::TryPrototypeChainLookup( Goto(&loop); } } - Bind(&if_keyisindex); + BIND(&if_keyisindex); { - Variable var_holder(this, MachineRepresentation::kTagged, receiver); - Variable var_holder_map(this, MachineRepresentation::kTagged, map); - Variable var_holder_instance_type(this, MachineRepresentation::kWord32, - instance_type); + VARIABLE(var_holder, MachineRepresentation::kTagged, receiver); + VARIABLE(var_holder_map, MachineRepresentation::kTagged, map); + VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32, + instance_type); Variable* merged_variables[] = {&var_holder, &var_holder_map, &var_holder_instance_type}; Label loop(this, arraysize(merged_variables), merged_variables); Goto(&loop); - Bind(&loop); + BIND(&loop); { Label next_proto(this); lookup_element_in_holder(receiver, var_holder.value(), var_holder_map.value(), var_holder_instance_type.value(), var_index.value(), &next_proto, if_bailout); - Bind(&next_proto); + BIND(&next_proto); Node* proto = LoadMapPrototype(var_holder_map.value()); Label if_not_null(this); Branch(WordEqual(proto, NullConstant()), if_end, &if_not_null); - Bind(&if_not_null); + BIND(&if_not_null); Node* map = LoadMap(proto); Node* instance_type = LoadMapInstanceType(map); @@ -5390,7 +5563,7 @@ void CodeStubAssembler::TryPrototypeChainLookup( Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, Node* object) { - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); Label return_false(this), return_true(this), return_runtime(this, Label::kDeferred), return_result(this); @@ -5414,7 +5587,7 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, &instanceof_cache_miss); var_result.Bind(LoadRoot(Heap::kInstanceofCacheAnswerRootIndex)); Goto(&return_result); - Bind(&instanceof_cache_miss); + BIND(&instanceof_cache_miss); } // Goto runtime if {callable} is a Smi. @@ -5444,8 +5617,8 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, LoadObjectField(callable, JSFunction::kPrototypeOrInitialMapOffset); { Label callable_prototype_valid(this); - Variable var_callable_prototype(this, MachineRepresentation::kTagged, - callable_prototype); + VARIABLE(var_callable_prototype, MachineRepresentation::kTagged, + callable_prototype); // Resolve the "prototype" if the {callable} has an initial map. Afterwards // the {callable_prototype} will be either the JSReceiver prototype object @@ -5459,7 +5632,7 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, var_callable_prototype.Bind( LoadObjectField(callable_prototype, Map::kPrototypeOffset)); Goto(&callable_prototype_valid); - Bind(&callable_prototype_valid); + BIND(&callable_prototype_valid); callable_prototype = var_callable_prototype.value(); } @@ -5469,10 +5642,10 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, StoreRoot(Heap::kInstanceofCacheMapRootIndex, object_map); // Loop through the prototype chain looking for the {callable} prototype. - Variable var_object_map(this, MachineRepresentation::kTagged, object_map); + VARIABLE(var_object_map, MachineRepresentation::kTagged, object_map); Label loop(this, &var_object_map); Goto(&loop); - Bind(&loop); + BIND(&loop); { Node* object_map = var_object_map.value(); @@ -5499,17 +5672,17 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, Goto(&loop); } - Bind(&return_true); + BIND(&return_true); StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(true)); var_result.Bind(BooleanConstant(true)); Goto(&return_result); - Bind(&return_false); + BIND(&return_false); StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(false)); var_result.Bind(BooleanConstant(false)); Goto(&return_result); - Bind(&return_runtime); + BIND(&return_runtime); { // Invalidate the global instanceof cache. StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, SmiConstant(0)); @@ -5519,7 +5692,7 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, } Goto(&return_result); - Bind(&return_result); + BIND(&return_result); return var_result.value(); } @@ -5574,27 +5747,14 @@ void CodeStubAssembler::UpdateFeedback(Node* feedback, Node* feedback_vector, } Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) { - Variable var_receiver_map(this, MachineRepresentation::kTagged); - Label load_smi_map(this, Label::kDeferred), load_receiver_map(this), - if_result(this); - - Branch(TaggedIsSmi(receiver), &load_smi_map, &load_receiver_map); - Bind(&load_smi_map); - { - var_receiver_map.Bind(LoadRoot(Heap::kHeapNumberMapRootIndex)); - Goto(&if_result); - } - Bind(&load_receiver_map); - { - var_receiver_map.Bind(LoadMap(receiver)); - Goto(&if_result); - } - Bind(&if_result); - return var_receiver_map.value(); + return Select(TaggedIsSmi(receiver), + [=] { return LoadRoot(Heap::kHeapNumberMapRootIndex); }, + [=] { return LoadMap(receiver); }, + MachineRepresentation::kTagged); } Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) { - Variable var_intptr_key(this, MachineType::PointerRepresentation()); + VARIABLE(var_intptr_key, MachineType::PointerRepresentation()); Label done(this, &var_intptr_key), key_is_smi(this); GotoIf(TaggedIsSmi(key), &key_is_smi); // Try to convert a heap number to a Smi. @@ -5607,13 +5767,13 @@ Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) { Goto(&done); } - Bind(&key_is_smi); + BIND(&key_is_smi); { var_intptr_key.Bind(SmiUntag(key)); Goto(&done); } - Bind(&done); + BIND(&done); return var_intptr_key.value(); } @@ -5654,7 +5814,7 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key, Node* elements = LoadElements(receiver); Node* elements_length = LoadAndUntagFixedArrayBaseLength(elements); - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); if (!is_load) { var_result.Bind(value); } @@ -5668,7 +5828,7 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key, LoadFixedArrayElement(elements, IntPtrAdd(key, intptr_two)); Branch(WordEqual(mapped_index, TheHoleConstant()), &if_unmapped, &if_mapped); - Bind(&if_mapped); + BIND(&if_mapped); { CSA_ASSERT(this, TaggedIsSmi(mapped_index)); mapped_index = SmiUntag(mapped_index); @@ -5688,7 +5848,7 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key, Goto(&end); } - Bind(&if_unmapped); + BIND(&if_unmapped); { Node* backing_store = LoadFixedArrayElement(elements, 1); GotoIf(WordNotEqual(LoadMap(backing_store), FixedArrayMapConstant()), @@ -5709,7 +5869,7 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key, Goto(&end); } - Bind(&end); + BIND(&end); return var_result.value(); } @@ -5780,19 +5940,19 @@ Node* CodeStubAssembler::Int32ToUint8Clamped(Node* int32_value) { Label done(this); Node* int32_zero = Int32Constant(0); Node* int32_255 = Int32Constant(255); - Variable var_value(this, MachineRepresentation::kWord32, int32_value); + VARIABLE(var_value, MachineRepresentation::kWord32, int32_value); GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done); var_value.Bind(int32_zero); GotoIf(Int32LessThan(int32_value, int32_zero), &done); var_value.Bind(int32_255); Goto(&done); - Bind(&done); + BIND(&done); return var_value.value(); } Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) { Label done(this); - Variable var_value(this, MachineRepresentation::kWord32, Int32Constant(0)); + VARIABLE(var_value, MachineRepresentation::kWord32, Int32Constant(0)); GotoIf(Float64LessThanOrEqual(float64_value, Float64Constant(0.0)), &done); var_value.Bind(Int32Constant(255)); GotoIf(Float64LessThanOrEqual(Float64Constant(255.0), float64_value), &done); @@ -5801,7 +5961,7 @@ Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) { var_value.Bind(TruncateFloat64ToWord32(rounded_value)); Goto(&done); } - Bind(&done); + BIND(&done); return var_value.value(); } @@ -5831,7 +5991,7 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( return nullptr; } - Variable var_result(this, rep); + VARIABLE(var_result, rep); Label done(this, &var_result), if_smi(this); GotoIf(TaggedIsSmi(input), &if_smi); // Try to convert a heap number to a Smi. @@ -5853,7 +6013,7 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( Goto(&done); } - Bind(&if_smi); + BIND(&if_smi); { Node* value = SmiToWord32(input); if (rep == MachineRepresentation::kFloat32) { @@ -5870,7 +6030,7 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( Goto(&done); } - Bind(&done); + BIND(&done); return var_result.value(); } @@ -5931,7 +6091,7 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, StoreElement(backing_store, elements_kind, key, value, parameter_mode); Goto(&done); - Bind(&done); + BIND(&done); return; } DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) || @@ -5970,7 +6130,7 @@ Node* CodeStubAssembler::CheckForCapacityGrow(Node* object, Node* elements, Node* key, ParameterMode mode, bool is_js_array, Label* bailout) { - Variable checked_elements(this, MachineRepresentation::kTagged); + VARIABLE(checked_elements, MachineRepresentation::kTagged); Label grow_case(this), no_grow_case(this), done(this); Node* condition; @@ -5981,7 +6141,7 @@ Node* CodeStubAssembler::CheckForCapacityGrow(Node* object, Node* elements, } Branch(condition, &grow_case, &no_grow_case); - Bind(&grow_case); + BIND(&grow_case); { Node* current_capacity = TaggedToParameter(LoadFixedArrayBaseLength(elements), mode); @@ -5997,7 +6157,7 @@ Node* CodeStubAssembler::CheckForCapacityGrow(Node* object, Node* elements, checked_elements.Bind(new_elements); Goto(&fits_capacity); } - Bind(&fits_capacity); + BIND(&fits_capacity); if (is_js_array) { Node* new_length = IntPtrAdd(key, IntPtrOrSmiConstant(1, mode)); @@ -6007,14 +6167,14 @@ Node* CodeStubAssembler::CheckForCapacityGrow(Node* object, Node* elements, Goto(&done); } - Bind(&no_grow_case); + BIND(&no_grow_case); { GotoIfNot(UintPtrLessThan(key, length), bailout); checked_elements.Bind(elements); Goto(&done); } - Bind(&done); + BIND(&done); return checked_elements.value(); } @@ -6022,7 +6182,7 @@ Node* CodeStubAssembler::CopyElementsOnWrite(Node* object, Node* elements, ElementsKind kind, Node* length, ParameterMode mode, Label* bailout) { - Variable new_elements_var(this, MachineRepresentation::kTagged, elements); + VARIABLE(new_elements_var, MachineRepresentation::kTagged, elements); Label done(this); GotoIfNot( @@ -6038,7 +6198,7 @@ Node* CodeStubAssembler::CopyElementsOnWrite(Node* object, Node* elements, Goto(&done); } - Bind(&done); + BIND(&done); return new_elements_var.value(); } @@ -6073,7 +6233,7 @@ void CodeStubAssembler::TransitionElementsKind(Node* object, Node* map, GrowElementsCapacity(object, elements, from_kind, to_kind, array_length, elements_length, mode, bailout); Goto(&done); - Bind(&done); + BIND(&done); } StoreMap(object, map); @@ -6122,21 +6282,21 @@ void CodeStubAssembler::TrapAllocationMemento(Node* object, // If top is on the same page as the current object, we need to check whether // we are below top. - Bind(&top_check); + BIND(&top_check); { Branch(UintPtrGreaterThanOrEqual(memento_last_word, new_space_top), &no_memento_found, &map_check); } // Memento map check. - Bind(&map_check); + BIND(&map_check); { Node* memento_map = LoadObjectField(object, kMementoMapOffset); Branch( WordEqual(memento_map, LoadRoot(Heap::kAllocationMementoMapRootIndex)), memento_found, &no_memento_found); } - Bind(&no_memento_found); + BIND(&no_memento_found); Comment("] TrapAllocationMemento"); } @@ -6144,73 +6304,6 @@ Node* CodeStubAssembler::PageFromAddress(Node* address) { return WordAnd(address, IntPtrConstant(~Page::kPageAlignmentMask)); } -Node* CodeStubAssembler::EnumLength(Node* map) { - CSA_ASSERT(this, IsMap(map)); - Node* bitfield_3 = LoadMapBitField3(map); - Node* enum_length = DecodeWordFromWord32<Map::EnumLengthBits>(bitfield_3); - return SmiTag(enum_length); -} - -void CodeStubAssembler::CheckEnumCache(Node* receiver, Label* use_cache, - Label* use_runtime) { - Variable current_js_object(this, MachineRepresentation::kTagged, receiver); - - Variable current_map(this, MachineRepresentation::kTagged, - LoadMap(current_js_object.value())); - - // These variables are updated in the loop below. - Variable* loop_vars[2] = {¤t_js_object, ¤t_map}; - Label loop(this, 2, loop_vars), next(this); - - // Check if the enum length field is properly initialized, indicating that - // there is an enum cache. - { - Node* invalid_enum_cache_sentinel = - SmiConstant(Smi::FromInt(kInvalidEnumCacheSentinel)); - Node* enum_length = EnumLength(current_map.value()); - Branch(WordEqual(enum_length, invalid_enum_cache_sentinel), use_runtime, - &loop); - } - - // Check that there are no elements. |current_js_object| contains - // the current JS object we've reached through the prototype chain. - Bind(&loop); - { - Label if_elements(this), if_no_elements(this); - Node* elements = LoadElements(current_js_object.value()); - Node* empty_fixed_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex); - // Check that there are no elements. - Branch(WordEqual(elements, empty_fixed_array), &if_no_elements, - &if_elements); - Bind(&if_elements); - { - // Second chance, the object may be using the empty slow element - // dictionary. - Node* slow_empty_dictionary = - LoadRoot(Heap::kEmptySlowElementDictionaryRootIndex); - Branch(WordNotEqual(elements, slow_empty_dictionary), use_runtime, - &if_no_elements); - } - - Bind(&if_no_elements); - { - // Update map prototype. - current_js_object.Bind(LoadMapPrototype(current_map.value())); - Branch(WordEqual(current_js_object.value(), NullConstant()), use_cache, - &next); - } - } - - Bind(&next); - { - // For all objects but the receiver, check that the cache is empty. - current_map.Bind(LoadMap(current_js_object.value())); - Node* enum_length = EnumLength(current_map.value()); - Node* zero_constant = SmiConstant(Smi::kZero); - Branch(WordEqual(enum_length, zero_constant), &loop, use_runtime); - } -} - Node* CodeStubAssembler::CreateAllocationSiteInFeedbackVector( Node* feedback_vector, Node* slot) { Node* size = IntPtrConstant(AllocationSite::kSize); @@ -6281,7 +6374,7 @@ Node* CodeStubAssembler::BuildFastLoop( MachineRepresentation index_rep = (parameter_mode == INTPTR_PARAMETERS) ? MachineType::PointerRepresentation() : MachineRepresentation::kTaggedSigned; - Variable var(this, index_rep, start_index); + VARIABLE(var, index_rep, start_index); VariableList vars_copy(vars, zone()); vars_copy.Add(&var, zone()); Label loop(this, vars_copy); @@ -6294,7 +6387,7 @@ Node* CodeStubAssembler::BuildFastLoop( // it from the pre-header). The extra branch is slower in the case that the // loop actually iterates. Branch(WordEqual(var.value(), end_index), &after_loop, &loop); - Bind(&loop); + BIND(&loop); { if (advance_mode == IndexAdvanceMode::kPre) { Increment(var, increment, parameter_mode); @@ -6305,7 +6398,7 @@ Node* CodeStubAssembler::BuildFastLoop( } Branch(WordNotEqual(var.value(), end_index), &loop, &after_loop); } - Bind(&after_loop); + BIND(&after_loop); return var.value(); } @@ -6391,24 +6484,24 @@ void CodeStubAssembler::BranchIfNumericRelationalComparison( RelationalComparisonMode mode, Node* lhs, Node* rhs, Label* if_true, Label* if_false) { Label end(this); - Variable result(this, MachineRepresentation::kTagged); + VARIABLE(result, MachineRepresentation::kTagged); // Shared entry for floating point comparison. Label do_fcmp(this); - Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64), - var_fcmp_rhs(this, MachineRepresentation::kFloat64); + VARIABLE(var_fcmp_lhs, MachineRepresentation::kFloat64); + VARIABLE(var_fcmp_rhs, MachineRepresentation::kFloat64); // Check if the {lhs} is a Smi or a HeapObject. Label if_lhsissmi(this), if_lhsisnotsmi(this); Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); - Bind(&if_lhsissmi); + BIND(&if_lhsissmi); { // Check if {rhs} is a Smi or a HeapObject. Label if_rhsissmi(this), if_rhsisnotsmi(this); Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); - Bind(&if_rhsissmi); + BIND(&if_rhsissmi); { // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison. switch (mode) { @@ -6427,7 +6520,7 @@ void CodeStubAssembler::BranchIfNumericRelationalComparison( } } - Bind(&if_rhsisnotsmi); + BIND(&if_rhsisnotsmi); { CSA_ASSERT(this, IsHeapNumberMap(LoadMap(rhs))); // Convert the {lhs} and {rhs} to floating point values, and @@ -6438,7 +6531,7 @@ void CodeStubAssembler::BranchIfNumericRelationalComparison( } } - Bind(&if_lhsisnotsmi); + BIND(&if_lhsisnotsmi); { CSA_ASSERT(this, IsHeapNumberMap(LoadMap(lhs))); @@ -6446,7 +6539,7 @@ void CodeStubAssembler::BranchIfNumericRelationalComparison( Label if_rhsissmi(this), if_rhsisnotsmi(this); Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); - Bind(&if_rhsissmi); + BIND(&if_rhsissmi); { // Convert the {lhs} and {rhs} to floating point values, and // perform a floating point comparison. @@ -6455,7 +6548,7 @@ void CodeStubAssembler::BranchIfNumericRelationalComparison( Goto(&do_fcmp); } - Bind(&if_rhsisnotsmi); + BIND(&if_rhsisnotsmi); { CSA_ASSERT(this, IsHeapNumberMap(LoadMap(rhs))); @@ -6467,7 +6560,7 @@ void CodeStubAssembler::BranchIfNumericRelationalComparison( } } - Bind(&do_fcmp); + BIND(&do_fcmp); { // Load the {lhs} and {rhs} floating point values. Node* lhs = var_fcmp_lhs.value(); @@ -6495,28 +6588,28 @@ void CodeStubAssembler::GotoUnlessNumberLessThan(Node* lhs, Node* rhs, Label* if_false) { Label if_true(this); BranchIfNumericRelationalComparison(kLessThan, lhs, rhs, &if_true, if_false); - Bind(&if_true); + BIND(&if_true); } Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Node* lhs, Node* rhs, Node* context) { Label return_true(this), return_false(this), end(this); - Variable result(this, MachineRepresentation::kTagged); + VARIABLE(result, MachineRepresentation::kTagged); // Shared entry for floating point comparison. Label do_fcmp(this); - Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64), - var_fcmp_rhs(this, MachineRepresentation::kFloat64); + VARIABLE(var_fcmp_lhs, MachineRepresentation::kFloat64); + VARIABLE(var_fcmp_rhs, MachineRepresentation::kFloat64); // We might need to loop several times due to ToPrimitive and/or ToNumber // conversions. - Variable var_lhs(this, MachineRepresentation::kTagged, lhs), - var_rhs(this, MachineRepresentation::kTagged, rhs); + VARIABLE(var_lhs, MachineRepresentation::kTagged, lhs); + VARIABLE(var_rhs, MachineRepresentation::kTagged, rhs); Variable* loop_vars[2] = {&var_lhs, &var_rhs}; Label loop(this, 2, loop_vars); Goto(&loop); - Bind(&loop); + BIND(&loop); { // Load the current {lhs} and {rhs} values. lhs = var_lhs.value(); @@ -6526,13 +6619,13 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Label if_lhsissmi(this), if_lhsisnotsmi(this); Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); - Bind(&if_lhsissmi); + BIND(&if_lhsissmi); { // Check if {rhs} is a Smi or a HeapObject. Label if_rhsissmi(this), if_rhsisnotsmi(this); Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); - Bind(&if_rhsissmi); + BIND(&if_rhsissmi); { // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison. switch (mode) { @@ -6551,7 +6644,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, } } - Bind(&if_rhsisnotsmi); + BIND(&if_rhsisnotsmi); { // Load the map of {rhs}. Node* rhs_map = LoadMap(rhs); @@ -6560,7 +6653,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred); Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber); - Bind(&if_rhsisnumber); + BIND(&if_rhsisnumber); { // Convert the {lhs} and {rhs} to floating point values, and // perform a floating point comparison. @@ -6569,7 +6662,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Goto(&do_fcmp); } - Bind(&if_rhsisnotnumber); + BIND(&if_rhsisnotnumber); { // Convert the {rhs} to a Number; we don't need to perform the // dedicated ToPrimitive(rhs, hint Number) operation, as the @@ -6582,7 +6675,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, } } - Bind(&if_lhsisnotsmi); + BIND(&if_lhsisnotsmi); { // Load the map of {lhs}. Node* lhs_map = LoadMap(lhs); @@ -6591,13 +6684,13 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Label if_rhsissmi(this), if_rhsisnotsmi(this); Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); - Bind(&if_rhsissmi); + BIND(&if_rhsissmi); { // Check if the {lhs} is a HeapNumber. Label if_lhsisnumber(this), if_lhsisnotnumber(this, Label::kDeferred); Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber); - Bind(&if_lhsisnumber); + BIND(&if_lhsisnumber); { // Convert the {lhs} and {rhs} to floating point values, and // perform a floating point comparison. @@ -6606,7 +6699,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Goto(&do_fcmp); } - Bind(&if_lhsisnotnumber); + BIND(&if_lhsisnotnumber); { // Convert the {lhs} to a Number; we don't need to perform the // dedicated ToPrimitive(lhs, hint Number) operation, as the @@ -6618,7 +6711,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, } } - Bind(&if_rhsisnotsmi); + BIND(&if_rhsisnotsmi); { // Load the map of {rhs}. Node* rhs_map = LoadMap(rhs); @@ -6627,14 +6720,14 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Label if_lhsisnumber(this), if_lhsisnotnumber(this); Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber); - Bind(&if_lhsisnumber); + BIND(&if_lhsisnumber); { // Check if {rhs} is also a HeapNumber. Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred); Branch(WordEqual(lhs_map, rhs_map), &if_rhsisnumber, &if_rhsisnotnumber); - Bind(&if_rhsisnumber); + BIND(&if_rhsisnumber); { // Convert the {lhs} and {rhs} to floating point values, and // perform a floating point comparison. @@ -6643,7 +6736,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Goto(&do_fcmp); } - Bind(&if_rhsisnotnumber); + BIND(&if_rhsisnotnumber); { // Convert the {rhs} to a Number; we don't need to perform // dedicated ToPrimitive(rhs, hint Number) operation, as the @@ -6655,7 +6748,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, } } - Bind(&if_lhsisnotnumber); + BIND(&if_lhsisnotnumber); { // Load the instance type of {lhs}. Node* lhs_instance_type = LoadMapInstanceType(lhs_map); @@ -6665,7 +6758,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring, &if_lhsisnotstring); - Bind(&if_lhsisstring); + BIND(&if_lhsisstring); { // Load the instance type of {rhs}. Node* rhs_instance_type = LoadMapInstanceType(rhs_map); @@ -6676,7 +6769,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, &if_rhsisnotstring); - Bind(&if_rhsisstring); + BIND(&if_rhsisstring); { // Both {lhs} and {rhs} are strings. switch (mode) { @@ -6706,7 +6799,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, } } - Bind(&if_rhsisnotstring); + BIND(&if_rhsisnotstring); { // The {lhs} is a String, while {rhs} is neither a Number nor a // String, so we need to call ToPrimitive(rhs, hint Number) if @@ -6718,7 +6811,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Branch(IsJSReceiverInstanceType(rhs_instance_type), &if_rhsisreceiver, &if_rhsisnotreceiver); - Bind(&if_rhsisreceiver); + BIND(&if_rhsisreceiver); { // Convert {rhs} to a primitive first passing Number hint. Callable callable = CodeFactory::NonPrimitiveToPrimitive( @@ -6727,7 +6820,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Goto(&loop); } - Bind(&if_rhsisnotreceiver); + BIND(&if_rhsisnotreceiver); { // Convert both {lhs} and {rhs} to Number. Callable callable = CodeFactory::ToNumber(isolate()); @@ -6738,7 +6831,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, } } - Bind(&if_lhsisnotstring); + BIND(&if_lhsisnotstring); { // The {lhs} is neither a Number nor a String, so we need to call // ToPrimitive(lhs, hint Number) if {lhs} is a receiver or @@ -6749,7 +6842,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Branch(IsJSReceiverInstanceType(lhs_instance_type), &if_lhsisreceiver, &if_lhsisnotreceiver); - Bind(&if_lhsisreceiver); + BIND(&if_lhsisreceiver); { // Convert {lhs} to a primitive first passing Number hint. Callable callable = CodeFactory::NonPrimitiveToPrimitive( @@ -6758,7 +6851,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, Goto(&loop); } - Bind(&if_lhsisnotreceiver); + BIND(&if_lhsisnotreceiver); { // Convert both {lhs} and {rhs} to Number. Callable callable = CodeFactory::ToNumber(isolate()); @@ -6772,7 +6865,7 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, } } - Bind(&do_fcmp); + BIND(&do_fcmp); { // Load the {lhs} and {rhs} floating point values. Node* lhs = var_fcmp_lhs.value(); @@ -6796,19 +6889,19 @@ Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode, } } - Bind(&return_true); + BIND(&return_true); { result.Bind(BooleanConstant(true)); Goto(&end); } - Bind(&return_false); + BIND(&return_false); { result.Bind(BooleanConstant(false)); Goto(&end); } - Bind(&end); + BIND(&end); return result.value(); } @@ -6828,7 +6921,7 @@ void GenerateEqual_Same(CodeStubAssembler* assembler, Node* value, assembler->Branch(assembler->TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); - assembler->Bind(&if_valueisnotsmi); + assembler->BIND(&if_valueisnotsmi); { // Load the map of {value}. Node* value_map = assembler->LoadMap(value); @@ -6838,7 +6931,7 @@ void GenerateEqual_Same(CodeStubAssembler* assembler, Node* value, assembler->Branch(assembler->IsHeapNumberMap(value_map), &if_valueisnumber, &if_valueisnotnumber); - assembler->Bind(&if_valueisnumber); + assembler->BIND(&if_valueisnumber); { // Convert {value} (and therefore {rhs}) to floating point value. Node* value_value = assembler->LoadHeapNumberValue(value); @@ -6847,18 +6940,17 @@ void GenerateEqual_Same(CodeStubAssembler* assembler, Node* value, assembler->BranchIfFloat64IsNaN(value_value, if_notequal, if_equal); } - assembler->Bind(&if_valueisnotnumber); + assembler->BIND(&if_valueisnotnumber); assembler->Goto(if_equal); } - assembler->Bind(&if_valueissmi); + assembler->BIND(&if_valueissmi); assembler->Goto(if_equal); } } // namespace // ES6 section 7.2.12 Abstract Equality Comparison -Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, - Node* context) { +Node* CodeStubAssembler::Equal(Node* lhs, Node* rhs, Node* context) { // This is a slightly optimized version of Object::Equals represented as // scheduled TurboFan graph utilizing the CodeStubAssembler. Whenever you // change something functionality wise in here, remember to update the @@ -6866,21 +6958,21 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Label if_equal(this), if_notequal(this), do_rhsstringtonumber(this, Label::kDeferred), end(this); - Variable result(this, MachineRepresentation::kTagged); + VARIABLE(result, MachineRepresentation::kTagged); // Shared entry for floating point comparison. Label do_fcmp(this); - Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64), - var_fcmp_rhs(this, MachineRepresentation::kFloat64); + VARIABLE(var_fcmp_lhs, MachineRepresentation::kFloat64); + VARIABLE(var_fcmp_rhs, MachineRepresentation::kFloat64); // We might need to loop several times due to ToPrimitive and/or ToNumber // conversions. - Variable var_lhs(this, MachineRepresentation::kTagged, lhs), - var_rhs(this, MachineRepresentation::kTagged, rhs); + VARIABLE(var_lhs, MachineRepresentation::kTagged, lhs); + VARIABLE(var_rhs, MachineRepresentation::kTagged, rhs); Variable* loop_vars[2] = {&var_lhs, &var_rhs}; Label loop(this, 2, loop_vars); Goto(&loop); - Bind(&loop); + BIND(&loop); { // Load the current {lhs} and {rhs} values. lhs = var_lhs.value(); @@ -6890,31 +6982,31 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Label if_same(this), if_notsame(this); Branch(WordEqual(lhs, rhs), &if_same, &if_notsame); - Bind(&if_same); + BIND(&if_same); { // The {lhs} and {rhs} reference the exact same value, yet we need special // treatment for HeapNumber, as NaN is not equal to NaN. GenerateEqual_Same(this, lhs, &if_equal, &if_notequal); } - Bind(&if_notsame); + BIND(&if_notsame); { // Check if {lhs} is a Smi or a HeapObject. Label if_lhsissmi(this), if_lhsisnotsmi(this); Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); - Bind(&if_lhsissmi); + BIND(&if_lhsissmi); { // Check if {rhs} is a Smi or a HeapObject. Label if_rhsissmi(this), if_rhsisnotsmi(this); Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); - Bind(&if_rhsissmi); + BIND(&if_rhsissmi); // We have already checked for {lhs} and {rhs} being the same value, so // if both are Smis when we get here they must not be equal. Goto(&if_notequal); - Bind(&if_rhsisnotsmi); + BIND(&if_rhsisnotsmi); { // Load the map of {rhs}. Node* rhs_map = LoadMap(rhs); @@ -6923,7 +7015,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Label if_rhsisnumber(this), if_rhsisnotnumber(this); Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber); - Bind(&if_rhsisnumber); + BIND(&if_rhsisnumber); { // Convert {lhs} and {rhs} to floating point values, and // perform a floating point comparison. @@ -6932,7 +7024,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Goto(&do_fcmp); } - Bind(&if_rhsisnotnumber); + BIND(&if_rhsisnotnumber); { // Load the instance type of the {rhs}. Node* rhs_instance_type = LoadMapInstanceType(rhs_map); @@ -6943,7 +7035,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, &if_rhsisnotstring); - Bind(&if_rhsisstring); + BIND(&if_rhsisstring); { // The {rhs} is a String and the {lhs} is a Smi; we need // to convert the {rhs} to a Number and compare the output to @@ -6951,21 +7043,21 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Goto(&do_rhsstringtonumber); } - Bind(&if_rhsisnotstring); + BIND(&if_rhsisnotstring); { // Check if the {rhs} is a Boolean. Label if_rhsisboolean(this), if_rhsisnotboolean(this); Branch(IsBooleanMap(rhs_map), &if_rhsisboolean, &if_rhsisnotboolean); - Bind(&if_rhsisboolean); + BIND(&if_rhsisboolean); { // The {rhs} is a Boolean, load its number value. var_rhs.Bind(LoadObjectField(rhs, Oddball::kToNumberOffset)); Goto(&loop); } - Bind(&if_rhsisnotboolean); + BIND(&if_rhsisnotboolean); { // Check if the {rhs} is a Receiver. STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); @@ -6974,7 +7066,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Branch(IsJSReceiverInstanceType(rhs_instance_type), &if_rhsisreceiver, &if_rhsisnotreceiver); - Bind(&if_rhsisreceiver); + BIND(&if_rhsisreceiver); { // Convert {rhs} to a primitive first (passing no hint). Callable callable = @@ -6983,7 +7075,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Goto(&loop); } - Bind(&if_rhsisnotreceiver); + BIND(&if_rhsisnotreceiver); Goto(&if_notequal); } } @@ -6991,13 +7083,13 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, } } - Bind(&if_lhsisnotsmi); + BIND(&if_lhsisnotsmi); { // Check if {rhs} is a Smi or a HeapObject. Label if_rhsissmi(this), if_rhsisnotsmi(this); Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); - Bind(&if_rhsissmi); + BIND(&if_rhsissmi); { // The {lhs} is a HeapObject and the {rhs} is a Smi; swapping {lhs} // and {rhs} is not observable and doesn't matter for the result, so @@ -7008,7 +7100,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Goto(&loop); } - Bind(&if_rhsisnotsmi); + BIND(&if_rhsisnotsmi); { Label if_lhsisstring(this), if_lhsisnumber(this), if_lhsissymbol(this), if_lhsisoddball(this), @@ -7045,7 +7137,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, delete case_labels[i]; } - Bind(&if_lhsisstring); + BIND(&if_lhsisstring); { // Check if {rhs} is also a String. Label if_rhsisstring(this, Label::kDeferred), @@ -7053,18 +7145,16 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, &if_rhsisnotstring); - Bind(&if_rhsisstring); + BIND(&if_rhsisstring); { // Both {lhs} and {rhs} are of type String, just do the // string comparison then. - Callable callable = (mode == kDontNegateResult) - ? CodeFactory::StringEqual(isolate()) - : CodeFactory::StringNotEqual(isolate()); + Callable callable = CodeFactory::StringEqual(isolate()); result.Bind(CallStub(callable, context, lhs, rhs)); Goto(&end); } - Bind(&if_rhsisnotstring); + BIND(&if_rhsisnotstring); { // The {lhs} is a String and the {rhs} is some other HeapObject. // Swapping {lhs} and {rhs} is not observable and doesn't matter @@ -7076,14 +7166,14 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, } } - Bind(&if_lhsisnumber); + BIND(&if_lhsisnumber); { // Check if {rhs} is also a HeapNumber. Label if_rhsisnumber(this), if_rhsisnotnumber(this); Branch(Word32Equal(lhs_instance_type, rhs_instance_type), &if_rhsisnumber, &if_rhsisnotnumber); - Bind(&if_rhsisnumber); + BIND(&if_rhsisnumber); { // Convert {lhs} and {rhs} to floating point values, and // perform a floating point comparison. @@ -7092,7 +7182,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Goto(&do_fcmp); } - Bind(&if_rhsisnotnumber); + BIND(&if_rhsisnotnumber); { // The {lhs} is a Number, the {rhs} is some other HeapObject. Label if_rhsisstring(this, Label::kDeferred), @@ -7100,7 +7190,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, &if_rhsisnotstring); - Bind(&if_rhsisstring); + BIND(&if_rhsisstring); { // The {rhs} is a String and the {lhs} is a HeapNumber; we need // to convert the {rhs} to a Number and compare the output to @@ -7108,7 +7198,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Goto(&do_rhsstringtonumber); } - Bind(&if_rhsisnotstring); + BIND(&if_rhsisnotstring); { // Check if the {rhs} is a JSReceiver. Label if_rhsisreceiver(this), if_rhsisnotreceiver(this); @@ -7116,7 +7206,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Branch(IsJSReceiverInstanceType(rhs_instance_type), &if_rhsisreceiver, &if_rhsisnotreceiver); - Bind(&if_rhsisreceiver); + BIND(&if_rhsisreceiver); { // The {lhs} is a Primitive and the {rhs} is a JSReceiver. // Swapping {lhs} and {rhs} is not observable and doesn't @@ -7128,14 +7218,14 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Goto(&loop); } - Bind(&if_rhsisnotreceiver); + BIND(&if_rhsisnotreceiver); { // Check if {rhs} is a Boolean. Label if_rhsisboolean(this), if_rhsisnotboolean(this); Branch(IsBooleanMap(rhs_map), &if_rhsisboolean, &if_rhsisnotboolean); - Bind(&if_rhsisboolean); + BIND(&if_rhsisboolean); { // The {rhs} is a Boolean, convert it to a Smi first. var_rhs.Bind( @@ -7143,14 +7233,14 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Goto(&loop); } - Bind(&if_rhsisnotboolean); + BIND(&if_rhsisnotboolean); Goto(&if_notequal); } } } } - Bind(&if_lhsisoddball); + BIND(&if_lhsisoddball); { // The {lhs} is an Oddball and {rhs} is some other HeapObject. Label if_lhsisboolean(this), if_lhsisnotboolean(this); @@ -7158,20 +7248,20 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Branch(WordEqual(lhs_map, boolean_map), &if_lhsisboolean, &if_lhsisnotboolean); - Bind(&if_lhsisboolean); + BIND(&if_lhsisboolean); { // The {lhs} is a Boolean, check if {rhs} is also a Boolean. Label if_rhsisboolean(this), if_rhsisnotboolean(this); Branch(WordEqual(rhs_map, boolean_map), &if_rhsisboolean, &if_rhsisnotboolean); - Bind(&if_rhsisboolean); + BIND(&if_rhsisboolean); { // Both {lhs} and {rhs} are distinct Boolean values. Goto(&if_notequal); } - Bind(&if_rhsisnotboolean); + BIND(&if_rhsisnotboolean); { // Convert the {lhs} to a Number first. var_lhs.Bind(LoadObjectField(lhs, Oddball::kToNumberOffset)); @@ -7179,7 +7269,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, } } - Bind(&if_lhsisnotboolean); + BIND(&if_lhsisnotboolean); { // The {lhs} is either Null or Undefined; check if the {rhs} is // undetectable (i.e. either also Null or Undefined or some @@ -7193,7 +7283,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, } } - Bind(&if_lhsissymbol); + BIND(&if_lhsissymbol); { // Check if the {rhs} is a JSReceiver. Label if_rhsisreceiver(this), if_rhsisnotreceiver(this); @@ -7201,7 +7291,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Branch(IsJSReceiverInstanceType(rhs_instance_type), &if_rhsisreceiver, &if_rhsisnotreceiver); - Bind(&if_rhsisreceiver); + BIND(&if_rhsisreceiver); { // The {lhs} is a Primitive and the {rhs} is a JSReceiver. // Swapping {lhs} and {rhs} is not observable and doesn't @@ -7212,7 +7302,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Goto(&loop); } - Bind(&if_rhsisnotreceiver); + BIND(&if_rhsisnotreceiver); { // The {rhs} is not a JSReceiver and also not the same Symbol // as the {lhs}, so this is equality check is considered false. @@ -7220,7 +7310,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, } } - Bind(&if_lhsisreceiver); + BIND(&if_lhsisreceiver); { // Check if the {rhs} is also a JSReceiver. Label if_rhsisreceiver(this), if_rhsisnotreceiver(this); @@ -7228,14 +7318,14 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Branch(IsJSReceiverInstanceType(rhs_instance_type), &if_rhsisreceiver, &if_rhsisnotreceiver); - Bind(&if_rhsisreceiver); + BIND(&if_rhsisreceiver); { // Both {lhs} and {rhs} are different JSReceiver references, so // this cannot be considered equal. Goto(&if_notequal); } - Bind(&if_rhsisnotreceiver); + BIND(&if_rhsisnotreceiver); { // Check if {rhs} is Null or Undefined (an undetectable check // is sufficient here, since we already know that {rhs} is not @@ -7249,7 +7339,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Int32Constant(0)), &if_rhsisnotundetectable, &if_rhsisundetectable); - Bind(&if_rhsisundetectable); + BIND(&if_rhsisundetectable); { // Check if {lhs} is an undetectable JSReceiver. Node* lhs_bitfield = LoadMapBitField(lhs_map); @@ -7260,7 +7350,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, &if_notequal, &if_equal); } - Bind(&if_rhsisnotundetectable); + BIND(&if_rhsisnotundetectable); { // The {rhs} is some Primitive different from Null and // Undefined, need to convert {lhs} to Primitive first. @@ -7275,7 +7365,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, } } - Bind(&do_rhsstringtonumber); + BIND(&do_rhsstringtonumber); { Callable callable = CodeFactory::StringToNumber(isolate()); var_rhs.Bind(CallStub(callable, context, rhs)); @@ -7283,7 +7373,7 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, } } - Bind(&do_fcmp); + BIND(&do_fcmp); { // Load the {lhs} and {rhs} floating point values. Node* lhs = var_fcmp_lhs.value(); @@ -7293,24 +7383,23 @@ Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs, Branch(Float64Equal(lhs, rhs), &if_equal, &if_notequal); } - Bind(&if_equal); + BIND(&if_equal); { - result.Bind(BooleanConstant(mode == kDontNegateResult)); + result.Bind(TrueConstant()); Goto(&end); } - Bind(&if_notequal); + BIND(&if_notequal); { - result.Bind(BooleanConstant(mode == kNegateResult)); + result.Bind(FalseConstant()); Goto(&end); } - Bind(&end); + BIND(&end); return result.value(); } -Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, - Node* context) { +Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs) { // Here's pseudo-code for the algorithm below in case of kDontNegateResult // mode; for kNegateResult mode we properly negate the result. // @@ -7356,20 +7445,20 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, // } Label if_equal(this), if_notequal(this), end(this); - Variable result(this, MachineRepresentation::kTagged); + VARIABLE(result, MachineRepresentation::kTagged); // Check if {lhs} and {rhs} refer to the same object. Label if_same(this), if_notsame(this); Branch(WordEqual(lhs, rhs), &if_same, &if_notsame); - Bind(&if_same); + BIND(&if_same); { // The {lhs} and {rhs} reference the exact same value, yet we need special // treatment for HeapNumber, as NaN is not equal to NaN. GenerateEqual_Same(this, lhs, &if_equal, &if_notequal); } - Bind(&if_notsame); + BIND(&if_notsame); { // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber // and String they can still be considered equal. @@ -7378,7 +7467,7 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Label if_lhsissmi(this), if_lhsisnotsmi(this); Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); - Bind(&if_lhsisnotsmi); + BIND(&if_lhsisnotsmi); { // Load the map of {lhs}. Node* lhs_map = LoadMap(lhs); @@ -7387,13 +7476,13 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Label if_lhsisnumber(this), if_lhsisnotnumber(this); Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber); - Bind(&if_lhsisnumber); + BIND(&if_lhsisnumber); { // Check if {rhs} is a Smi or a HeapObject. Label if_rhsissmi(this), if_rhsisnotsmi(this); Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); - Bind(&if_rhsissmi); + BIND(&if_rhsissmi); { // Convert {lhs} and {rhs} to floating point values. Node* lhs_value = LoadHeapNumberValue(lhs); @@ -7403,7 +7492,7 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal); } - Bind(&if_rhsisnotsmi); + BIND(&if_rhsisnotsmi); { // Load the map of {rhs}. Node* rhs_map = LoadMap(rhs); @@ -7412,7 +7501,7 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Label if_rhsisnumber(this), if_rhsisnotnumber(this); Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber); - Bind(&if_rhsisnumber); + BIND(&if_rhsisnumber); { // Convert {lhs} and {rhs} to floating point values. Node* lhs_value = LoadHeapNumberValue(lhs); @@ -7422,21 +7511,21 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal); } - Bind(&if_rhsisnotnumber); + BIND(&if_rhsisnotnumber); Goto(&if_notequal); } } - Bind(&if_lhsisnotnumber); + BIND(&if_lhsisnotnumber); { // Check if {rhs} is a Smi or a HeapObject. Label if_rhsissmi(this), if_rhsisnotsmi(this); Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); - Bind(&if_rhsissmi); + BIND(&if_rhsissmi); Goto(&if_notequal); - Bind(&if_rhsisnotsmi); + BIND(&if_rhsisnotsmi); { // Load the instance type of {lhs}. Node* lhs_instance_type = LoadMapInstanceType(lhs_map); @@ -7446,7 +7535,7 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring, &if_lhsisnotstring); - Bind(&if_lhsisstring); + BIND(&if_lhsisstring); { // Load the instance type of {rhs}. Node* rhs_instance_type = LoadInstanceType(rhs); @@ -7457,26 +7546,24 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, &if_rhsisnotstring); - Bind(&if_rhsisstring); + BIND(&if_rhsisstring); { - Callable callable = (mode == kDontNegateResult) - ? CodeFactory::StringEqual(isolate()) - : CodeFactory::StringNotEqual(isolate()); - result.Bind(CallStub(callable, context, lhs, rhs)); + Callable callable = CodeFactory::StringEqual(isolate()); + result.Bind(CallStub(callable, NoContextConstant(), lhs, rhs)); Goto(&end); } - Bind(&if_rhsisnotstring); + BIND(&if_rhsisnotstring); Goto(&if_notequal); } - Bind(&if_lhsisnotstring); + BIND(&if_lhsisnotstring); Goto(&if_notequal); } } } - Bind(&if_lhsissmi); + BIND(&if_lhsissmi); { // We already know that {lhs} and {rhs} are not reference equal, and {lhs} // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a @@ -7486,10 +7573,10 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Label if_rhsissmi(this), if_rhsisnotsmi(this); Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); - Bind(&if_rhsissmi); + BIND(&if_rhsissmi); Goto(&if_notequal); - Bind(&if_rhsisnotsmi); + BIND(&if_rhsisnotsmi); { // Load the map of the {rhs}. Node* rhs_map = LoadMap(rhs); @@ -7498,7 +7585,7 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Label if_rhsisnumber(this), if_rhsisnotnumber(this); Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber); - Bind(&if_rhsisnumber); + BIND(&if_rhsisnumber); { // Convert {lhs} and {rhs} to floating point values. Node* lhs_value = SmiToFloat64(lhs); @@ -7508,33 +7595,33 @@ Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs, Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal); } - Bind(&if_rhsisnotnumber); + BIND(&if_rhsisnotnumber); Goto(&if_notequal); } } } - Bind(&if_equal); + BIND(&if_equal); { - result.Bind(BooleanConstant(mode == kDontNegateResult)); + result.Bind(TrueConstant()); Goto(&end); } - Bind(&if_notequal); + BIND(&if_notequal); { - result.Bind(BooleanConstant(mode == kNegateResult)); + result.Bind(FalseConstant()); Goto(&end); } - Bind(&end); + BIND(&end); return result.value(); } // ECMA#sec-samevalue // This algorithm differs from the Strict Equality Comparison Algorithm in its // treatment of signed zeroes and NaNs. -Node* CodeStubAssembler::SameValue(Node* lhs, Node* rhs, Node* context) { - Variable var_result(this, MachineRepresentation::kWord32); +Node* CodeStubAssembler::SameValue(Node* lhs, Node* rhs) { + VARIABLE(var_result, MachineRepresentation::kWord32); Label strict_equal(this), out(this); Node* const int_false = Int32Constant(0); @@ -7543,7 +7630,7 @@ Node* CodeStubAssembler::SameValue(Node* lhs, Node* rhs, Node* context) { Label if_equal(this), if_notequal(this); Branch(WordEqual(lhs, rhs), &if_equal, &if_notequal); - Bind(&if_equal); + BIND(&if_equal); { // This covers the case when {lhs} == {rhs}. We can simply return true // because SameValue considers two NaNs to be equal. @@ -7552,7 +7639,7 @@ Node* CodeStubAssembler::SameValue(Node* lhs, Node* rhs, Node* context) { Goto(&out); } - Bind(&if_notequal); + BIND(&if_notequal); { // This covers the case when {lhs} != {rhs}. We only handle numbers here // and defer to StrictEqual for the rest. @@ -7563,7 +7650,7 @@ Node* CodeStubAssembler::SameValue(Node* lhs, Node* rhs, Node* context) { Label if_lhsisnan(this), if_lhsnotnan(this); BranchIfFloat64IsNaN(lhs_float, &if_lhsisnan, &if_lhsnotnan); - Bind(&if_lhsisnan); + BIND(&if_lhsisnan); { // Return true iff {rhs} is NaN. @@ -7574,13 +7661,13 @@ Node* CodeStubAssembler::SameValue(Node* lhs, Node* rhs, Node* context) { Goto(&out); } - Bind(&if_lhsnotnan); + BIND(&if_lhsnotnan); { Label if_floatisequal(this), if_floatnotequal(this); Branch(Float64Equal(lhs_float, rhs_float), &if_floatisequal, &if_floatnotequal); - Bind(&if_floatisequal); + BIND(&if_floatisequal); { // We still need to handle the case when {lhs} and {rhs} are -0.0 and // 0.0 (or vice versa). Compare the high word to @@ -7597,7 +7684,7 @@ Node* CodeStubAssembler::SameValue(Node* lhs, Node* rhs, Node* context) { Goto(&out); } - Bind(&if_floatnotequal); + BIND(&if_floatnotequal); { var_result.Bind(int_false); Goto(&out); @@ -7605,43 +7692,15 @@ Node* CodeStubAssembler::SameValue(Node* lhs, Node* rhs, Node* context) { } } - Bind(&strict_equal); + BIND(&strict_equal); { - Node* const is_equal = StrictEqual(kDontNegateResult, lhs, rhs, context); + Node* const is_equal = StrictEqual(lhs, rhs); Node* const result = WordEqual(is_equal, TrueConstant()); var_result.Bind(result); Goto(&out); } - Bind(&out); - return var_result.value(); -} - -Node* CodeStubAssembler::ForInFilter(Node* key, Node* object, Node* context) { - Label return_undefined(this, Label::kDeferred), return_to_name(this), - end(this); - - Variable var_result(this, MachineRepresentation::kTagged); - - Node* has_property = - HasProperty(object, key, context, Runtime::kForInHasProperty); - - Branch(WordEqual(has_property, BooleanConstant(true)), &return_to_name, - &return_undefined); - - Bind(&return_to_name); - { - var_result.Bind(ToName(context, key)); - Goto(&end); - } - - Bind(&return_undefined); - { - var_result.Bind(UndefinedConstant()); - Goto(&end); - } - - Bind(&end); + BIND(&out); return var_result.value(); } @@ -7660,44 +7719,47 @@ Node* CodeStubAssembler::HasProperty( }; CodeStubAssembler::LookupInHolder lookup_element_in_holder = - [this, &return_true](Node* receiver, Node* holder, Node* holder_map, - Node* holder_instance_type, Node* index, - Label* next_holder, Label* if_bailout) { + [this, &return_true, &return_false]( + Node* receiver, Node* holder, Node* holder_map, + Node* holder_instance_type, Node* index, Label* next_holder, + Label* if_bailout) { TryLookupElement(holder, holder_map, holder_instance_type, index, - &return_true, next_holder, if_bailout); + &return_true, &return_false, next_holder, if_bailout); }; TryPrototypeChainLookup(object, key, lookup_property_in_holder, lookup_element_in_holder, &return_false, &call_runtime); - Variable result(this, MachineRepresentation::kTagged); - Bind(&return_true); + VARIABLE(result, MachineRepresentation::kTagged); + BIND(&return_true); { result.Bind(BooleanConstant(true)); Goto(&end); } - Bind(&return_false); + BIND(&return_false); { result.Bind(BooleanConstant(false)); Goto(&end); } - Bind(&call_runtime); + BIND(&call_runtime); { result.Bind( CallRuntime(fallback_runtime_function_id, context, object, key)); Goto(&end); } - Bind(&end); + BIND(&end); return result.value(); } Node* CodeStubAssembler::ClassOf(Node* value) { - Variable var_result(this, MachineRepresentation::kTaggedPointer); - Label if_function(this, Label::kDeferred), if_object(this, Label::kDeferred), + VARIABLE(var_result, MachineRepresentation::kTaggedPointer); + Label if_function_template_info(this, Label::kDeferred), + if_no_class_name(this, Label::kDeferred), + if_function(this, Label::kDeferred), if_object(this, Label::kDeferred), if_primitive(this, Label::kDeferred), return_result(this); // Check if {value} is a Smi. @@ -7720,6 +7782,8 @@ Node* CodeStubAssembler::ClassOf(Node* value) { // Load the {value}s constructor, and check that it's a JSFunction. Node* constructor = LoadMapConstructor(value_map); + GotoIf(HasInstanceType(constructor, FUNCTION_TEMPLATE_INFO_TYPE), + &if_function_template_info); GotoIfNot(IsJSFunction(constructor), &if_object); // Return the instance class name for the {constructor}. @@ -7730,24 +7794,36 @@ Node* CodeStubAssembler::ClassOf(Node* value) { var_result.Bind(instance_class_name); Goto(&return_result); - Bind(&if_function); + // For remote objects the constructor might be given as FTI. + BIND(&if_function_template_info); + Node* class_name = + LoadObjectField(constructor, FunctionTemplateInfo::kClassNameOffset); + GotoIf(IsUndefined(class_name), &if_no_class_name); + var_result.Bind(class_name); + Goto(&return_result); + + BIND(&if_no_class_name); + var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex)); + Goto(&return_result); + + BIND(&if_function); var_result.Bind(LoadRoot(Heap::kFunction_stringRootIndex)); Goto(&return_result); - Bind(&if_object); + BIND(&if_object); var_result.Bind(LoadRoot(Heap::kObject_stringRootIndex)); Goto(&return_result); - Bind(&if_primitive); + BIND(&if_primitive); var_result.Bind(NullConstant()); Goto(&return_result); - Bind(&return_result); + BIND(&return_result); return var_result.value(); } -Node* CodeStubAssembler::Typeof(Node* value, Node* context) { - Variable result_var(this, MachineRepresentation::kTagged); +Node* CodeStubAssembler::Typeof(Node* value) { + VARIABLE(result_var, MachineRepresentation::kTagged); Label return_number(this, Label::kDeferred), if_oddball(this), return_function(this), return_undefined(this), return_object(this), @@ -7782,44 +7858,44 @@ Node* CodeStubAssembler::Typeof(Node* value, Node* context) { result_var.Bind(HeapConstant(isolate()->factory()->symbol_string())); Goto(&return_result); - Bind(&return_number); + BIND(&return_number); { result_var.Bind(HeapConstant(isolate()->factory()->number_string())); Goto(&return_result); } - Bind(&if_oddball); + BIND(&if_oddball); { Node* type = LoadObjectField(value, Oddball::kTypeOfOffset); result_var.Bind(type); Goto(&return_result); } - Bind(&return_function); + BIND(&return_function); { result_var.Bind(HeapConstant(isolate()->factory()->function_string())); Goto(&return_result); } - Bind(&return_undefined); + BIND(&return_undefined); { result_var.Bind(HeapConstant(isolate()->factory()->undefined_string())); Goto(&return_result); } - Bind(&return_object); + BIND(&return_object); { result_var.Bind(HeapConstant(isolate()->factory()->object_string())); Goto(&return_result); } - Bind(&return_string); + BIND(&return_string); { result_var.Bind(HeapConstant(isolate()->factory()->string_string())); Goto(&return_result); } - Bind(&return_result); + BIND(&return_result); return result_var.value(); } @@ -7828,7 +7904,7 @@ Node* CodeStubAssembler::GetSuperConstructor(Node* active_function, CSA_ASSERT(this, IsJSFunction(active_function)); Label is_not_constructor(this, Label::kDeferred), out(this); - Variable result(this, MachineRepresentation::kTagged); + VARIABLE(result, MachineRepresentation::kTagged); Node* map = LoadMap(active_function); Node* prototype = LoadMapPrototype(map); @@ -7838,20 +7914,20 @@ Node* CodeStubAssembler::GetSuperConstructor(Node* active_function, result.Bind(prototype); Goto(&out); - Bind(&is_not_constructor); + BIND(&is_not_constructor); { CallRuntime(Runtime::kThrowNotSuperConstructor, context, prototype, active_function); Unreachable(); } - Bind(&out); + BIND(&out); return result.value(); } Node* CodeStubAssembler::InstanceOf(Node* object, Node* callable, Node* context) { - Variable var_result(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); Label if_notcallable(this, Label::kDeferred), if_notreceiver(this, Label::kDeferred), if_otherhandler(this), if_nohandler(this, Label::kDeferred), return_true(this), @@ -7862,8 +7938,8 @@ Node* CodeStubAssembler::InstanceOf(Node* object, Node* callable, GotoIfNot(IsJSReceiver(callable), &if_notreceiver); // Load the @@hasInstance property from {callable}. - Node* inst_of_handler = CallStub(CodeFactory::GetProperty(isolate()), context, - callable, HasInstanceSymbolConstant()); + Node* inst_of_handler = + GetProperty(context, callable, HasInstanceSymbolConstant()); // Optimize for the likely case where {inst_of_handler} is the builtin // Function.prototype[@@hasInstance] method, and emit a direct call in @@ -7882,7 +7958,7 @@ Node* CodeStubAssembler::InstanceOf(Node* object, Node* callable, Goto(&return_result); } - Bind(&if_otherhandler); + BIND(&if_otherhandler); { // Check if there's actually an {inst_of_handler}. GotoIf(IsNull(inst_of_handler), &if_nohandler); @@ -7897,7 +7973,7 @@ Node* CodeStubAssembler::InstanceOf(Node* object, Node* callable, BranchIfToBooleanIsTrue(result, &return_true, &return_false); } - Bind(&if_nohandler); + BIND(&if_nohandler); { // Ensure that the {callable} is actually Callable. GotoIfNot(IsCallable(callable), &if_notcallable); @@ -7909,37 +7985,37 @@ Node* CodeStubAssembler::InstanceOf(Node* object, Node* callable, Goto(&return_result); } - Bind(&if_notcallable); + BIND(&if_notcallable); { CallRuntime(Runtime::kThrowNonCallableInInstanceOfCheck, context); Unreachable(); } - Bind(&if_notreceiver); + BIND(&if_notreceiver); { CallRuntime(Runtime::kThrowNonObjectInInstanceOfCheck, context); Unreachable(); } - Bind(&return_true); + BIND(&return_true); var_result.Bind(TrueConstant()); Goto(&return_result); - Bind(&return_false); + BIND(&return_false); var_result.Bind(FalseConstant()); Goto(&return_result); - Bind(&return_result); + BIND(&return_result); return var_result.value(); } Node* CodeStubAssembler::NumberInc(Node* value) { - Variable var_result(this, MachineRepresentation::kTagged), - var_finc_value(this, MachineRepresentation::kFloat64); + VARIABLE(var_result, MachineRepresentation::kTagged); + VARIABLE(var_finc_value, MachineRepresentation::kFloat64); Label if_issmi(this), if_isnotsmi(this), do_finc(this), end(this); Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi); - Bind(&if_issmi); + BIND(&if_issmi); { // Try fast Smi addition first. Node* one = SmiConstant(Smi::FromInt(1)); @@ -7951,18 +8027,18 @@ Node* CodeStubAssembler::NumberInc(Node* value) { Label if_overflow(this), if_notoverflow(this); Branch(overflow, &if_overflow, &if_notoverflow); - Bind(&if_notoverflow); + BIND(&if_notoverflow); var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair))); Goto(&end); - Bind(&if_overflow); + BIND(&if_overflow); { var_finc_value.Bind(SmiToFloat64(value)); Goto(&do_finc); } } - Bind(&if_isnotsmi); + BIND(&if_isnotsmi); { // Check if the value is a HeapNumber. CSA_ASSERT(this, IsHeapNumberMap(LoadMap(value))); @@ -7972,7 +8048,7 @@ Node* CodeStubAssembler::NumberInc(Node* value) { Goto(&do_finc); } - Bind(&do_finc); + BIND(&do_finc); { Node* finc_value = var_finc_value.value(); Node* one = Float64Constant(1.0); @@ -7981,7 +8057,59 @@ Node* CodeStubAssembler::NumberInc(Node* value) { Goto(&end); } - Bind(&end); + BIND(&end); + return var_result.value(); +} + +Node* CodeStubAssembler::NumberDec(Node* value) { + VARIABLE(var_result, MachineRepresentation::kTagged); + VARIABLE(var_fdec_value, MachineRepresentation::kFloat64); + Label if_issmi(this), if_isnotsmi(this), do_fdec(this), end(this); + Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi); + + BIND(&if_issmi); + { + // Try fast Smi addition first. + Node* one = SmiConstant(Smi::FromInt(1)); + Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(value), + BitcastTaggedToWord(one)); + Node* overflow = Projection(1, pair); + + // Check if the Smi addition overflowed. + Label if_overflow(this), if_notoverflow(this); + Branch(overflow, &if_overflow, &if_notoverflow); + + BIND(&if_notoverflow); + var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair))); + Goto(&end); + + BIND(&if_overflow); + { + var_fdec_value.Bind(SmiToFloat64(value)); + Goto(&do_fdec); + } + } + + BIND(&if_isnotsmi); + { + // Check if the value is a HeapNumber. + CSA_ASSERT(this, IsHeapNumberMap(LoadMap(value))); + + // Load the HeapNumber value. + var_fdec_value.Bind(LoadHeapNumberValue(value)); + Goto(&do_fdec); + } + + BIND(&do_fdec); + { + Node* fdec_value = var_fdec_value.value(); + Node* minus_one = Float64Constant(-1.0); + Node* fdec_result = Float64Add(fdec_value, minus_one); + var_result.Bind(AllocateHeapNumberWithValue(fdec_result)); + Goto(&end); + } + + BIND(&end); return var_result.value(); } @@ -7990,7 +8118,7 @@ void CodeStubAssembler::GotoIfNotNumber(Node* input, Label* is_not_number) { GotoIf(TaggedIsSmi(input), &is_number); Node* input_map = LoadMap(input); Branch(IsHeapNumberMap(input_map), &is_number, is_not_number); - Bind(&is_number); + BIND(&is_number); } void CodeStubAssembler::GotoIfNumber(Node* input, Label* is_number) { @@ -8036,9 +8164,9 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, // Assert: Type(array) is Object CSA_ASSERT(this, IsJSReceiverInstanceType(array_type)); - Variable var_result(this, MachineRepresentation::kTagged); - Variable var_map_index(this, MachineType::PointerRepresentation()); - Variable var_array_map(this, MachineRepresentation::kTagged); + VARIABLE(var_result, MachineRepresentation::kTagged); + VARIABLE(var_map_index, MachineType::PointerRepresentation()); + VARIABLE(var_array_map, MachineRepresentation::kTagged); Label return_result(this); Label allocate_iterator(this); @@ -8052,13 +8180,13 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), &if_istypedarray, &if_isgeneric); - Bind(&if_isgeneric); + BIND(&if_isgeneric); { Label if_isfast(this), if_isslow(this); BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, &if_isfast, &if_isslow); - Bind(&if_isfast); + BIND(&if_isfast); { var_map_index.Bind( IntPtrConstant(Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX)); @@ -8066,7 +8194,7 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, Goto(&allocate_iterator); } - Bind(&if_isslow); + BIND(&if_isslow); { var_map_index.Bind( IntPtrConstant(Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX)); @@ -8075,7 +8203,7 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, } } - Bind(&if_istypedarray); + BIND(&if_istypedarray); { var_map_index.Bind( IntPtrConstant(Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX)); @@ -8087,20 +8215,20 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), &if_istypedarray, &if_isgeneric); - Bind(&if_isgeneric); + BIND(&if_isgeneric); { Label if_isfast(this), if_isslow(this); BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, &if_isfast, &if_isslow); - Bind(&if_isfast); + BIND(&if_isfast); { Label if_ispacked(this), if_isholey(this); Node* elements_kind = LoadMapElementsKind(array_map); Branch(IsHoleyFastElementsKind(elements_kind), &if_isholey, &if_ispacked); - Bind(&if_isholey); + BIND(&if_isholey); { // Fast holey JSArrays can treat the hole as undefined if the // protector cell is valid, and the prototype chain is unchanged from @@ -8132,7 +8260,7 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, prototype = LoadMapPrototype(map); Branch(IsNull(prototype), &if_ispacked, &if_isslow); } - Bind(&if_ispacked); + BIND(&if_ispacked); { Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset), @@ -8150,7 +8278,7 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, } } - Bind(&if_isslow); + BIND(&if_isslow); { Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex), IntPtrConstant(kSlowIteratorOffset)); @@ -8160,7 +8288,7 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, } } - Bind(&if_istypedarray); + BIND(&if_istypedarray); { Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex - UINT8_ELEMENTS), @@ -8176,7 +8304,7 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, } } - Bind(&allocate_iterator); + BIND(&allocate_iterator); { Node* map = LoadFixedArrayElement(LoadNativeContext(context), var_map_index.value()); @@ -8184,7 +8312,7 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, Goto(&return_result); } - Bind(&return_result); + BIND(&return_result); return var_result.value(); } @@ -8205,6 +8333,16 @@ Node* CodeStubAssembler::AllocateJSArrayIterator(Node* array, Node* array_map, return iterator; } +Node* CodeStubAssembler::ArraySpeciesCreate(Node* context, Node* originalArray, + Node* len) { + // TODO(mvstanton): Install a fast path as well, which avoids the runtime + // call. + Node* constructor = + CallRuntime(Runtime::kArraySpeciesConstructor, context, originalArray); + return ConstructJS(CodeFactory::Construct(isolate()), context, constructor, + len); +} + Node* CodeStubAssembler::IsDetachedBuffer(Node* buffer) { CSA_ASSERT(this, HasInstanceType(buffer, JS_ARRAY_BUFFER_TYPE)); @@ -8373,16 +8511,14 @@ Node* CodeStubAssembler::AllocatePromiseReactionJobInfo( Node* CodeStubAssembler::MarkerIsFrameType(Node* marker_or_function, StackFrame::Type frame_type) { - return WordEqual( - marker_or_function, - IntPtrConstant(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR))); + return WordEqual(marker_or_function, + IntPtrConstant(StackFrame::TypeToMarker(frame_type))); } Node* CodeStubAssembler::MarkerIsNotFrameType(Node* marker_or_function, StackFrame::Type frame_type) { - return WordNotEqual( - marker_or_function, - IntPtrConstant(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR))); + return WordNotEqual(marker_or_function, + IntPtrConstant(StackFrame::TypeToMarker(frame_type))); } void CodeStubAssembler::Print(const char* s) { |