Index: src/builtins/arm64/builtins-arm64.cc |
diff --git a/src/builtins/arm64/builtins-arm64.cc b/src/builtins/arm64/builtins-arm64.cc |
index 88af03a49457d1b8ce2fdd32ed594573dd387fbb..25430cc5b8a00cda26472bc37cea062faff358ff 100644 |
--- a/src/builtins/arm64/builtins-arm64.cc |
+++ b/src/builtins/arm64/builtins-arm64.cc |
@@ -2176,7 +2176,8 @@ void Builtins::Generate_Apply(MacroAssembler* masm) { |
// Create the list of arguments from the array-like argumentsList. |
{ |
- Label create_arguments, create_array, create_runtime, done_create; |
+ Label create_arguments, create_array, create_holey_array, create_runtime, |
+ done_create; |
__ JumpIfSmi(arguments_list, &create_runtime); |
// Load native context. |
@@ -2198,7 +2199,7 @@ void Builtins::Generate_Apply(MacroAssembler* masm) { |
__ B(eq, &create_arguments); |
// Check if argumentsList is a fast JSArray. |
- __ CompareInstanceType(arguments_list_map, native_context, JS_ARRAY_TYPE); |
+ __ CompareInstanceType(arguments_list_map, x10, JS_ARRAY_TYPE); |
__ B(eq, &create_array); |
// Ask the runtime to create the list (actually a FixedArray). |
@@ -2223,14 +2224,42 @@ void Builtins::Generate_Apply(MacroAssembler* masm) { |
__ Mov(args, x10); |
__ B(&done_create); |
+ // For holey JSArrays we need to check that the array prototype chain |
+ // protector is intact and our prototype is the Array.prototype actually. |
+ __ Bind(&create_holey_array); |
+ // -- x2 : arguments_list_map |
+ // -- x4 : native_context |
+ Register arguments_list_prototype = x2; |
+ __ Ldr(arguments_list_prototype, |
+ FieldMemOperand(arguments_list_map, Map::kPrototypeOffset)); |
+ __ Ldr(x10, ContextMemOperand(native_context, |
+ Context::INITIAL_ARRAY_PROTOTYPE_INDEX)); |
+ __ Cmp(arguments_list_prototype, x10); |
+ __ B(ne, &create_runtime); |
+ __ LoadRoot(x10, Heap::kArrayProtectorRootIndex); |
+ __ Ldrsw(x11, UntagSmiFieldMemOperand(x10, PropertyCell::kValueOffset)); |
+ __ Cmp(x11, Isolate::kProtectorValid); |
+ __ B(ne, &create_runtime); |
+ __ Ldrsw(len, |
+ UntagSmiFieldMemOperand(arguments_list, JSArray::kLengthOffset)); |
+ __ Ldr(args, FieldMemOperand(arguments_list, JSArray::kElementsOffset)); |
+ __ B(&done_create); |
+ |
// Try to create the list from a JSArray object. |
__ Bind(&create_array); |
__ Ldr(x10, FieldMemOperand(arguments_list_map, Map::kBitField2Offset)); |
__ DecodeField<Map::ElementsKindBits>(x10); |
STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); |
+ STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
STATIC_ASSERT(FAST_ELEMENTS == 2); |
- // Branch for anything that's not FAST_{SMI_}ELEMENTS. |
- __ TestAndBranchIfAnySet(x10, ~FAST_ELEMENTS, &create_runtime); |
+ STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); |
+ // Check if it is a holey array, the order of the cmp is important as |
+ // anything higher than FAST_HOLEY_ELEMENTS will fall back to runtime. |
+ __ Cmp(x10, FAST_HOLEY_ELEMENTS); |
+ __ B(hi, &create_runtime); |
+ // Only FAST_XXX after this point, FAST_HOLEY_XXX are odd values. |
+ __ Tbnz(x10, 0, &create_holey_array); |
+ // FAST_SMI_ELEMENTS or FAST_ELEMENTS after this point. |
__ Ldrsw(len, |
UntagSmiFieldMemOperand(arguments_list, JSArray::kLengthOffset)); |
__ Ldr(args, FieldMemOperand(arguments_list, JSArray::kElementsOffset)); |
@@ -2264,16 +2293,24 @@ void Builtins::Generate_Apply(MacroAssembler* masm) { |
// Push arguments onto the stack (thisArgument is already on the stack). |
{ |
- Label done, loop; |
+ Label done, push, loop; |
Register src = x4; |
__ Add(src, args, FixedArray::kHeaderSize - kHeapObjectTag); |
__ Mov(x0, len); // The 'len' argument for Call() or Construct(). |
__ Cbz(len, &done); |
+ Register the_hole_value = x11; |
+ Register undefined_value = x12; |
+ // We do not use the CompareRoot macro as it would do a LoadRoot behind the |
+ // scenes and we want to avoid that in a loop. |
+ __ LoadRoot(the_hole_value, Heap::kTheHoleValueRootIndex); |
+ __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); |
__ Claim(len); |
__ Bind(&loop); |
__ Sub(len, len, 1); |
__ Ldr(x10, MemOperand(src, kPointerSize, PostIndex)); |
+ __ Cmp(x10, the_hole_value); |
+ __ Csel(x10, x10, undefined_value, ne); |
__ Poke(x10, Operand(len, LSL, kPointerSizeLog2)); |
__ Cbnz(len, &loop); |
__ Bind(&done); |