Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_ARM | 5 #if V8_TARGET_ARCH_ARM |
| 6 | 6 |
| 7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
| 9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
| 10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| (...skipping 1129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1140 __ bind(&loop_header); | 1140 __ bind(&loop_header); |
| 1141 __ ldr(scratch, MemOperand(index, -kPointerSize, PostIndex)); | 1141 __ ldr(scratch, MemOperand(index, -kPointerSize, PostIndex)); |
| 1142 __ push(scratch); | 1142 __ push(scratch); |
| 1143 __ bind(&loop_check); | 1143 __ bind(&loop_check); |
| 1144 __ cmp(index, limit); | 1144 __ cmp(index, limit); |
| 1145 __ b(gt, &loop_header); | 1145 __ b(gt, &loop_header); |
| 1146 } | 1146 } |
| 1147 | 1147 |
| 1148 // static | 1148 // static |
| 1149 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 1149 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
| 1150 MacroAssembler* masm, TailCallMode tail_call_mode, | 1150 MacroAssembler* masm, TailCallMode tail_call_mode, PushArgsMode mode) { |
|
rmcilroy
2017/01/23 15:38:44
nit - I'm not sure on the name, it seems a bit too
| |
| 1151 CallableType function_type) { | |
| 1152 // ----------- S t a t e ------------- | 1151 // ----------- S t a t e ------------- |
| 1153 // -- r0 : the number of arguments (not including the receiver) | 1152 // -- r0 : the number of arguments (not including the receiver) |
| 1154 // -- r2 : the address of the first argument to be pushed. Subsequent | 1153 // -- r2 : the address of the first argument to be pushed. Subsequent |
| 1155 // arguments should be consecutive above this, in the same order as | 1154 // arguments should be consecutive above this, in the same order as |
| 1156 // they are to be pushed onto the stack. | 1155 // they are to be pushed onto the stack. |
| 1157 // -- r1 : the target to call (can be any Object). | 1156 // -- r1 : the target to call (can be any Object). |
| 1158 // ----------------------------------- | 1157 // ----------------------------------- |
| 1159 Label stack_overflow; | 1158 Label stack_overflow; |
| 1160 | 1159 |
| 1161 __ add(r3, r0, Operand(1)); // Add one for receiver. | 1160 __ add(r3, r0, Operand(1)); // Add one for receiver. |
| 1162 | 1161 |
| 1163 // Push the arguments. r2, r4, r5 will be modified. | 1162 // Push the arguments. r2, r4, r5 will be modified. |
| 1164 Generate_InterpreterPushArgs(masm, r3, r2, r4, r5, &stack_overflow); | 1163 Generate_InterpreterPushArgs(masm, r3, r2, r4, r5, &stack_overflow); |
| 1165 | 1164 |
| 1166 // Call the target. | 1165 // Call the target. |
| 1167 if (function_type == CallableType::kJSFunction) { | 1166 if (mode == PushArgsMode::kJSFunction) { |
| 1168 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, | 1167 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, |
| 1169 tail_call_mode), | 1168 tail_call_mode), |
| 1170 RelocInfo::CODE_TARGET); | 1169 RelocInfo::CODE_TARGET); |
| 1170 } else if (mode == PushArgsMode::kWithFinalSpread) { | |
| 1171 __ Jump(masm->isolate()->builtins()->CallWithSpread(), | |
| 1172 RelocInfo::CODE_TARGET); | |
| 1171 } else { | 1173 } else { |
| 1172 DCHECK_EQ(function_type, CallableType::kAny); | |
| 1173 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 1174 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 1174 tail_call_mode), | 1175 tail_call_mode), |
| 1175 RelocInfo::CODE_TARGET); | 1176 RelocInfo::CODE_TARGET); |
| 1176 } | 1177 } |
| 1177 | 1178 |
| 1178 __ bind(&stack_overflow); | 1179 __ bind(&stack_overflow); |
| 1179 { | 1180 { |
| 1180 __ TailCallRuntime(Runtime::kThrowStackOverflow); | 1181 __ TailCallRuntime(Runtime::kThrowStackOverflow); |
| 1181 // Unreachable code. | 1182 // Unreachable code. |
| 1182 __ bkpt(0); | 1183 __ bkpt(0); |
| 1183 } | 1184 } |
| 1184 } | 1185 } |
| 1185 | 1186 |
| 1186 // static | 1187 // static |
| 1187 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( | 1188 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( |
| 1188 MacroAssembler* masm, PushArgsConstructMode mode) { | 1189 MacroAssembler* masm, PushArgsMode mode) { |
| 1189 // ----------- S t a t e ------------- | 1190 // ----------- S t a t e ------------- |
| 1190 // -- r0 : argument count (not including receiver) | 1191 // -- r0 : argument count (not including receiver) |
| 1191 // -- r3 : new target | 1192 // -- r3 : new target |
| 1192 // -- r1 : constructor to call | 1193 // -- r1 : constructor to call |
| 1193 // -- r2 : allocation site feedback if available, undefined otherwise. | 1194 // -- r2 : allocation site feedback if available, undefined otherwise. |
| 1194 // -- r4 : address of the first argument | 1195 // -- r4 : address of the first argument |
| 1195 // ----------------------------------- | 1196 // ----------------------------------- |
| 1196 Label stack_overflow; | 1197 Label stack_overflow; |
| 1197 | 1198 |
| 1198 // Push a slot for the receiver to be constructed. | 1199 // Push a slot for the receiver to be constructed. |
| 1199 __ mov(ip, Operand::Zero()); | 1200 __ mov(ip, Operand::Zero()); |
| 1200 __ push(ip); | 1201 __ push(ip); |
| 1201 | 1202 |
| 1202 // Push the arguments. r5, r4, r6 will be modified. | 1203 // Push the arguments. r5, r4, r6 will be modified. |
| 1203 Generate_InterpreterPushArgs(masm, r0, r4, r5, r6, &stack_overflow); | 1204 Generate_InterpreterPushArgs(masm, r0, r4, r5, r6, &stack_overflow); |
| 1204 | 1205 |
| 1205 __ AssertUndefinedOrAllocationSite(r2, r5); | 1206 __ AssertUndefinedOrAllocationSite(r2, r5); |
| 1206 if (mode == PushArgsConstructMode::kJSFunction) { | 1207 if (mode == PushArgsMode::kJSFunction) { |
| 1207 __ AssertFunction(r1); | 1208 __ AssertFunction(r1); |
| 1208 | 1209 |
| 1209 // Tail call to the function-specific construct stub (still in the caller | 1210 // Tail call to the function-specific construct stub (still in the caller |
| 1210 // context at this point). | 1211 // context at this point). |
| 1211 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1212 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1212 __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kConstructStubOffset)); | 1213 __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kConstructStubOffset)); |
| 1213 // Jump to the construct function. | 1214 // Jump to the construct function. |
| 1214 __ add(pc, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1215 __ add(pc, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 1215 } else if (mode == PushArgsConstructMode::kWithFinalSpread) { | 1216 } else if (mode == PushArgsMode::kWithFinalSpread) { |
| 1216 // Call the constructor with r0, r1, and r3 unmodified. | 1217 // Call the constructor with r0, r1, and r3 unmodified. |
| 1217 __ Jump(masm->isolate()->builtins()->ConstructWithSpread(), | 1218 __ Jump(masm->isolate()->builtins()->ConstructWithSpread(), |
| 1218 RelocInfo::CODE_TARGET); | 1219 RelocInfo::CODE_TARGET); |
| 1219 } else { | 1220 } else { |
| 1220 DCHECK_EQ(PushArgsConstructMode::kOther, mode); | 1221 DCHECK_EQ(PushArgsMode::kOther, mode); |
| 1221 // Call the constructor with r0, r1, and r3 unmodified. | 1222 // Call the constructor with r0, r1, and r3 unmodified. |
| 1222 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 1223 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 1223 } | 1224 } |
| 1224 | 1225 |
| 1225 __ bind(&stack_overflow); | 1226 __ bind(&stack_overflow); |
| 1226 { | 1227 { |
| 1227 __ TailCallRuntime(Runtime::kThrowStackOverflow); | 1228 __ TailCallRuntime(Runtime::kThrowStackOverflow); |
| 1228 // Unreachable code. | 1229 // Unreachable code. |
| 1229 __ bkpt(0); | 1230 __ bkpt(0); |
| 1230 } | 1231 } |
| (...skipping 1379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2610 | 2611 |
| 2611 // 3. Call to something that is not callable. | 2612 // 3. Call to something that is not callable. |
| 2612 __ bind(&non_callable); | 2613 __ bind(&non_callable); |
| 2613 { | 2614 { |
| 2614 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 2615 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 2615 __ Push(r1); | 2616 __ Push(r1); |
| 2616 __ CallRuntime(Runtime::kThrowCalledNonCallable); | 2617 __ CallRuntime(Runtime::kThrowCalledNonCallable); |
| 2617 } | 2618 } |
| 2618 } | 2619 } |
| 2619 | 2620 |
| 2620 // static | 2621 static void CheckSpreadAndPushToStack(MacroAssembler* masm) { |
| 2621 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { | |
| 2622 // ----------- S t a t e ------------- | |
| 2623 // -- r0 : the number of arguments (not including the receiver) | |
| 2624 // -- r1 : the constructor to call (checked to be a JSFunction) | |
| 2625 // -- r3 : the new target (checked to be a constructor) | |
| 2626 // ----------------------------------- | |
| 2627 __ AssertFunction(r1); | |
| 2628 | |
| 2629 // Calling convention for function specific ConstructStubs require | |
| 2630 // r2 to contain either an AllocationSite or undefined. | |
| 2631 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | |
| 2632 | |
| 2633 // Tail call to the function-specific construct stub (still in the caller | |
| 2634 // context at this point). | |
| 2635 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
| 2636 __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kConstructStubOffset)); | |
| 2637 __ add(pc, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); | |
| 2638 } | |
| 2639 | |
| 2640 // static | |
| 2641 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { | |
| 2642 // ----------- S t a t e ------------- | |
| 2643 // -- r0 : the number of arguments (not including the receiver) | |
| 2644 // -- r1 : the function to call (checked to be a JSBoundFunction) | |
| 2645 // -- r3 : the new target (checked to be a constructor) | |
| 2646 // ----------------------------------- | |
| 2647 __ AssertBoundFunction(r1); | |
| 2648 | |
| 2649 // Push the [[BoundArguments]] onto the stack. | |
| 2650 Generate_PushBoundArguments(masm); | |
| 2651 | |
| 2652 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. | |
| 2653 __ cmp(r1, r3); | |
| 2654 __ ldr(r3, FieldMemOperand(r1, JSBoundFunction::kBoundTargetFunctionOffset), | |
| 2655 eq); | |
| 2656 | |
| 2657 // Construct the [[BoundTargetFunction]] via the Construct builtin. | |
| 2658 __ ldr(r1, FieldMemOperand(r1, JSBoundFunction::kBoundTargetFunctionOffset)); | |
| 2659 __ mov(ip, Operand(ExternalReference(Builtins::kConstruct, masm->isolate()))); | |
| 2660 __ ldr(ip, MemOperand(ip)); | |
| 2661 __ add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); | |
| 2662 } | |
| 2663 | |
| 2664 // static | |
| 2665 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { | |
| 2666 // ----------- S t a t e ------------- | |
| 2667 // -- r0 : the number of arguments (not including the receiver) | |
| 2668 // -- r1 : the constructor to call (checked to be a JSProxy) | |
| 2669 // -- r3 : the new target (either the same as the constructor or | |
| 2670 // the JSFunction on which new was invoked initially) | |
| 2671 // ----------------------------------- | |
| 2672 | |
| 2673 // Call into the Runtime for Proxy [[Construct]]. | |
| 2674 __ Push(r1); | |
| 2675 __ Push(r3); | |
| 2676 // Include the pushed new_target, constructor and the receiver. | |
| 2677 __ add(r0, r0, Operand(3)); | |
| 2678 // Tail-call to the runtime. | |
| 2679 __ JumpToExternalReference( | |
| 2680 ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); | |
| 2681 } | |
| 2682 | |
| 2683 // static | |
| 2684 void Builtins::Generate_Construct(MacroAssembler* masm) { | |
| 2685 // ----------- S t a t e ------------- | |
| 2686 // -- r0 : the number of arguments (not including the receiver) | |
| 2687 // -- r1 : the constructor to call (can be any Object) | |
| 2688 // -- r3 : the new target (either the same as the constructor or | |
| 2689 // the JSFunction on which new was invoked initially) | |
| 2690 // ----------------------------------- | |
| 2691 | |
| 2692 // Check if target is a Smi. | |
| 2693 Label non_constructor; | |
| 2694 __ JumpIfSmi(r1, &non_constructor); | |
| 2695 | |
| 2696 // Dispatch based on instance type. | |
| 2697 __ CompareObjectType(r1, r4, r5, JS_FUNCTION_TYPE); | |
| 2698 __ Jump(masm->isolate()->builtins()->ConstructFunction(), | |
| 2699 RelocInfo::CODE_TARGET, eq); | |
| 2700 | |
| 2701 // Check if target has a [[Construct]] internal method. | |
| 2702 __ ldrb(r2, FieldMemOperand(r4, Map::kBitFieldOffset)); | |
| 2703 __ tst(r2, Operand(1 << Map::kIsConstructor)); | |
| 2704 __ b(eq, &non_constructor); | |
| 2705 | |
| 2706 // Only dispatch to bound functions after checking whether they are | |
| 2707 // constructors. | |
| 2708 __ cmp(r5, Operand(JS_BOUND_FUNCTION_TYPE)); | |
| 2709 __ Jump(masm->isolate()->builtins()->ConstructBoundFunction(), | |
| 2710 RelocInfo::CODE_TARGET, eq); | |
| 2711 | |
| 2712 // Only dispatch to proxies after checking whether they are constructors. | |
| 2713 __ cmp(r5, Operand(JS_PROXY_TYPE)); | |
| 2714 __ Jump(masm->isolate()->builtins()->ConstructProxy(), RelocInfo::CODE_TARGET, | |
| 2715 eq); | |
| 2716 | |
| 2717 // Called Construct on an exotic Object with a [[Construct]] internal method. | |
| 2718 { | |
| 2719 // Overwrite the original receiver with the (original) target. | |
| 2720 __ str(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); | |
| 2721 // Let the "call_as_constructor_delegate" take care of the rest. | |
| 2722 __ LoadNativeContextSlot(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, r1); | |
| 2723 __ Jump(masm->isolate()->builtins()->CallFunction(), | |
| 2724 RelocInfo::CODE_TARGET); | |
| 2725 } | |
| 2726 | |
| 2727 // Called Construct on an Object that doesn't have a [[Construct]] internal | |
| 2728 // method. | |
| 2729 __ bind(&non_constructor); | |
| 2730 __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), | |
| 2731 RelocInfo::CODE_TARGET); | |
| 2732 } | |
| 2733 | |
| 2734 // static | |
| 2735 void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) { | |
| 2736 // ----------- S t a t e ------------- | |
| 2737 // -- r0 : the number of arguments (not including the receiver) | |
| 2738 // -- r1 : the constructor to call (can be any Object) | |
| 2739 // -- r3 : the new target (either the same as the constructor or | |
| 2740 // the JSFunction on which new was invoked initially) | |
| 2741 // ----------------------------------- | |
| 2742 | |
| 2743 Register argc = r0; | 2622 Register argc = r0; |
| 2744 Register constructor = r1; | 2623 Register constructor = r1; |
| 2745 Register new_target = r3; | 2624 Register new_target = r3; |
| 2746 | 2625 |
| 2747 Register scratch = r2; | 2626 Register scratch = r2; |
| 2748 Register scratch2 = r6; | 2627 Register scratch2 = r6; |
| 2749 | 2628 |
| 2750 Register spread = r4; | 2629 Register spread = r4; |
| 2751 Register spread_map = r5; | 2630 Register spread_map = r5; |
| 2631 | |
| 2632 Register spread_len = r5; | |
| 2633 | |
| 2752 __ ldr(spread, MemOperand(sp, 0)); | 2634 __ ldr(spread, MemOperand(sp, 0)); |
| 2753 __ ldr(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset)); | 2635 __ ldr(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset)); |
| 2754 | 2636 |
| 2755 Label runtime_call, push_args; | 2637 Label runtime_call, push_args; |
| 2756 // Check that the spread is an array. | 2638 // Check that the spread is an array. |
| 2757 __ CompareInstanceType(spread_map, scratch, JS_ARRAY_TYPE); | 2639 __ CompareInstanceType(spread_map, scratch, JS_ARRAY_TYPE); |
| 2758 __ b(ne, &runtime_call); | 2640 __ b(ne, &runtime_call); |
| 2759 | 2641 |
| 2760 // Check that we have the original ArrayPrototype. | 2642 // Check that we have the original ArrayPrototype. |
| 2761 __ ldr(scratch, FieldMemOperand(spread_map, Map::kPrototypeOffset)); | 2643 __ ldr(scratch, FieldMemOperand(spread_map, Map::kPrototypeOffset)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2796 __ b(eq, &no_protector_check); | 2678 __ b(eq, &no_protector_check); |
| 2797 __ cmp(scratch, Operand(FAST_ELEMENTS)); | 2679 __ cmp(scratch, Operand(FAST_ELEMENTS)); |
| 2798 __ b(eq, &no_protector_check); | 2680 __ b(eq, &no_protector_check); |
| 2799 // Check the ArrayProtector cell. | 2681 // Check the ArrayProtector cell. |
| 2800 __ LoadRoot(scratch, Heap::kArrayProtectorRootIndex); | 2682 __ LoadRoot(scratch, Heap::kArrayProtectorRootIndex); |
| 2801 __ ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); | 2683 __ ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); |
| 2802 __ cmp(scratch, Operand(Smi::FromInt(Isolate::kProtectorValid))); | 2684 __ cmp(scratch, Operand(Smi::FromInt(Isolate::kProtectorValid))); |
| 2803 __ b(ne, &runtime_call); | 2685 __ b(ne, &runtime_call); |
| 2804 | 2686 |
| 2805 __ bind(&no_protector_check); | 2687 __ bind(&no_protector_check); |
| 2806 // Load the FixedArray backing store. | 2688 // Load the FixedArray backing store, but use the length from the array. |
| 2689 __ ldr(spread_len, FieldMemOperand(spread, JSArray::kLengthOffset)); | |
| 2690 __ SmiUntag(spread_len); | |
| 2807 __ ldr(spread, FieldMemOperand(spread, JSArray::kElementsOffset)); | 2691 __ ldr(spread, FieldMemOperand(spread, JSArray::kElementsOffset)); |
| 2808 __ b(&push_args); | 2692 __ b(&push_args); |
| 2809 | 2693 |
| 2810 __ bind(&runtime_call); | 2694 __ bind(&runtime_call); |
| 2811 { | 2695 { |
| 2812 // Call the builtin for the result of the spread. | 2696 // Call the builtin for the result of the spread. |
| 2813 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 2697 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 2814 __ SmiTag(argc); | 2698 __ SmiTag(argc); |
| 2815 __ Push(constructor); | 2699 __ Push(constructor); |
| 2816 __ Push(new_target); | 2700 __ Push(new_target); |
| 2817 __ Push(argc); | 2701 __ Push(argc); |
| 2818 __ Push(spread); | 2702 __ Push(spread); |
| 2819 __ CallRuntime(Runtime::kSpreadIterableFixed); | 2703 __ CallRuntime(Runtime::kSpreadIterableFixed); |
| 2820 __ mov(spread, r0); | 2704 __ mov(spread, r0); |
| 2821 __ Pop(argc); | 2705 __ Pop(argc); |
| 2822 __ Pop(new_target); | 2706 __ Pop(new_target); |
| 2823 __ Pop(constructor); | 2707 __ Pop(constructor); |
| 2824 __ SmiUntag(argc); | 2708 __ SmiUntag(argc); |
| 2825 } | 2709 } |
| 2826 | 2710 |
| 2827 Register spread_len = r5; | |
| 2828 __ bind(&push_args); | |
| 2829 { | 2711 { |
| 2830 // Pop the spread argument off the stack. | |
| 2831 __ Pop(scratch); | |
| 2832 // Calculate the new nargs including the result of the spread. | 2712 // Calculate the new nargs including the result of the spread. |
| 2833 __ ldr(spread_len, FieldMemOperand(spread, FixedArray::kLengthOffset)); | 2713 __ ldr(spread_len, FieldMemOperand(spread, FixedArray::kLengthOffset)); |
| 2834 __ SmiUntag(spread_len); | 2714 __ SmiUntag(spread_len); |
| 2715 | |
| 2716 __ bind(&push_args); | |
| 2835 // argc += spread_len - 1. Subtract 1 for the spread itself. | 2717 // argc += spread_len - 1. Subtract 1 for the spread itself. |
| 2836 __ add(argc, argc, spread_len); | 2718 __ add(argc, argc, spread_len); |
| 2837 __ sub(argc, argc, Operand(1)); | 2719 __ sub(argc, argc, Operand(1)); |
| 2720 | |
| 2721 // Pop the spread argument off the stack. | |
| 2722 __ Pop(scratch); | |
| 2838 } | 2723 } |
| 2839 | 2724 |
| 2840 // Check for stack overflow. | 2725 // Check for stack overflow. |
| 2841 { | 2726 { |
| 2842 // Check the stack for overflow. We are not trying to catch interruptions | 2727 // Check the stack for overflow. We are not trying to catch interruptions |
| 2843 // (i.e. debug break and preemption) here, so check the "real stack limit". | 2728 // (i.e. debug break and preemption) here, so check the "real stack limit". |
| 2844 Label done; | 2729 Label done; |
| 2845 __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); | 2730 __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); |
| 2846 // Make scratch the space we have left. The stack might already be | 2731 // Make scratch the space we have left. The stack might already be |
| 2847 // overflowed here which will cause scratch to become negative. | 2732 // overflowed here which will cause scratch to become negative. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2860 __ bind(&loop); | 2745 __ bind(&loop); |
| 2861 __ cmp(scratch, spread_len); | 2746 __ cmp(scratch, spread_len); |
| 2862 __ b(eq, &done); | 2747 __ b(eq, &done); |
| 2863 __ add(scratch2, spread, Operand(scratch, LSL, kPointerSizeLog2)); | 2748 __ add(scratch2, spread, Operand(scratch, LSL, kPointerSizeLog2)); |
| 2864 __ ldr(scratch2, FieldMemOperand(scratch2, FixedArray::kHeaderSize)); | 2749 __ ldr(scratch2, FieldMemOperand(scratch2, FixedArray::kHeaderSize)); |
| 2865 __ Push(scratch2); | 2750 __ Push(scratch2); |
| 2866 __ add(scratch, scratch, Operand(1)); | 2751 __ add(scratch, scratch, Operand(1)); |
| 2867 __ b(&loop); | 2752 __ b(&loop); |
| 2868 __ bind(&done); | 2753 __ bind(&done); |
| 2869 } | 2754 } |
| 2755 } | |
| 2870 | 2756 |
| 2871 // Dispatch. | 2757 // static |
| 2758 void Builtins::Generate_CallWithSpread(MacroAssembler* masm) { | |
| 2759 // ----------- S t a t e ------------- | |
| 2760 // -- r0 : the number of arguments (not including the receiver) | |
| 2761 // -- r1 : the constructor to call (can be any Object) | |
| 2762 // ----------------------------------- | |
| 2763 | |
| 2764 // CheckSpreadAndPushToStack will push r3 to save it. | |
| 2765 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); | |
| 2766 CheckSpreadAndPushToStack(masm); | |
| 2767 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | |
| 2768 TailCallMode::kDisallow), | |
| 2769 RelocInfo::CODE_TARGET); | |
| 2770 } | |
| 2771 | |
| 2772 // static | |
| 2773 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { | |
| 2774 // ----------- S t a t e ------------- | |
| 2775 // -- r0 : the number of arguments (not including the receiver) | |
| 2776 // -- r1 : the constructor to call (checked to be a JSFunction) | |
| 2777 // -- r3 : the new target (checked to be a constructor) | |
| 2778 // ----------------------------------- | |
| 2779 __ AssertFunction(r1); | |
| 2780 | |
| 2781 // Calling convention for function specific ConstructStubs require | |
| 2782 // r2 to contain either an AllocationSite or undefined. | |
| 2783 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | |
| 2784 | |
| 2785 // Tail call to the function-specific construct stub (still in the caller | |
| 2786 // context at this point). | |
| 2787 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
| 2788 __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kConstructStubOffset)); | |
| 2789 __ add(pc, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); | |
| 2790 } | |
| 2791 | |
| 2792 // static | |
| 2793 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { | |
| 2794 // ----------- S t a t e ------------- | |
| 2795 // -- r0 : the number of arguments (not including the receiver) | |
| 2796 // -- r1 : the function to call (checked to be a JSBoundFunction) | |
| 2797 // -- r3 : the new target (checked to be a constructor) | |
| 2798 // ----------------------------------- | |
| 2799 __ AssertBoundFunction(r1); | |
| 2800 | |
| 2801 // Push the [[BoundArguments]] onto the stack. | |
| 2802 Generate_PushBoundArguments(masm); | |
| 2803 | |
| 2804 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. | |
| 2805 __ cmp(r1, r3); | |
| 2806 __ ldr(r3, FieldMemOperand(r1, JSBoundFunction::kBoundTargetFunctionOffset), | |
| 2807 eq); | |
| 2808 | |
| 2809 // Construct the [[BoundTargetFunction]] via the Construct builtin. | |
| 2810 __ ldr(r1, FieldMemOperand(r1, JSBoundFunction::kBoundTargetFunctionOffset)); | |
| 2811 __ mov(ip, Operand(ExternalReference(Builtins::kConstruct, masm->isolate()))); | |
| 2812 __ ldr(ip, MemOperand(ip)); | |
| 2813 __ add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); | |
| 2814 } | |
| 2815 | |
| 2816 // static | |
| 2817 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { | |
| 2818 // ----------- S t a t e ------------- | |
| 2819 // -- r0 : the number of arguments (not including the receiver) | |
| 2820 // -- r1 : the constructor to call (checked to be a JSProxy) | |
| 2821 // -- r3 : the new target (either the same as the constructor or | |
| 2822 // the JSFunction on which new was invoked initially) | |
| 2823 // ----------------------------------- | |
| 2824 | |
| 2825 // Call into the Runtime for Proxy [[Construct]]. | |
| 2826 __ Push(r1); | |
| 2827 __ Push(r3); | |
| 2828 // Include the pushed new_target, constructor and the receiver. | |
| 2829 __ add(r0, r0, Operand(3)); | |
| 2830 // Tail-call to the runtime. | |
| 2831 __ JumpToExternalReference( | |
| 2832 ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); | |
| 2833 } | |
| 2834 | |
| 2835 // static | |
| 2836 void Builtins::Generate_Construct(MacroAssembler* masm) { | |
| 2837 // ----------- S t a t e ------------- | |
| 2838 // -- r0 : the number of arguments (not including the receiver) | |
| 2839 // -- r1 : the constructor to call (can be any Object) | |
| 2840 // -- r3 : the new target (either the same as the constructor or | |
| 2841 // the JSFunction on which new was invoked initially) | |
| 2842 // ----------------------------------- | |
| 2843 | |
| 2844 // Check if target is a Smi. | |
| 2845 Label non_constructor; | |
| 2846 __ JumpIfSmi(r1, &non_constructor); | |
| 2847 | |
| 2848 // Dispatch based on instance type. | |
| 2849 __ CompareObjectType(r1, r4, r5, JS_FUNCTION_TYPE); | |
| 2850 __ Jump(masm->isolate()->builtins()->ConstructFunction(), | |
| 2851 RelocInfo::CODE_TARGET, eq); | |
| 2852 | |
| 2853 // Check if target has a [[Construct]] internal method. | |
| 2854 __ ldrb(r2, FieldMemOperand(r4, Map::kBitFieldOffset)); | |
| 2855 __ tst(r2, Operand(1 << Map::kIsConstructor)); | |
| 2856 __ b(eq, &non_constructor); | |
| 2857 | |
| 2858 // Only dispatch to bound functions after checking whether they are | |
| 2859 // constructors. | |
| 2860 __ cmp(r5, Operand(JS_BOUND_FUNCTION_TYPE)); | |
| 2861 __ Jump(masm->isolate()->builtins()->ConstructBoundFunction(), | |
| 2862 RelocInfo::CODE_TARGET, eq); | |
| 2863 | |
| 2864 // Only dispatch to proxies after checking whether they are constructors. | |
| 2865 __ cmp(r5, Operand(JS_PROXY_TYPE)); | |
| 2866 __ Jump(masm->isolate()->builtins()->ConstructProxy(), RelocInfo::CODE_TARGET, | |
| 2867 eq); | |
| 2868 | |
| 2869 // Called Construct on an exotic Object with a [[Construct]] internal method. | |
| 2870 { | |
| 2871 // Overwrite the original receiver with the (original) target. | |
| 2872 __ str(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); | |
| 2873 // Let the "call_as_constructor_delegate" take care of the rest. | |
| 2874 __ LoadNativeContextSlot(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, r1); | |
| 2875 __ Jump(masm->isolate()->builtins()->CallFunction(), | |
| 2876 RelocInfo::CODE_TARGET); | |
| 2877 } | |
| 2878 | |
| 2879 // Called Construct on an Object that doesn't have a [[Construct]] internal | |
| 2880 // method. | |
| 2881 __ bind(&non_constructor); | |
| 2882 __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), | |
| 2883 RelocInfo::CODE_TARGET); | |
| 2884 } | |
| 2885 | |
| 2886 // static | |
| 2887 void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) { | |
| 2888 // ----------- S t a t e ------------- | |
| 2889 // -- r0 : the number of arguments (not including the receiver) | |
| 2890 // -- r1 : the constructor to call (can be any Object) | |
| 2891 // -- r3 : the new target (either the same as the constructor or | |
| 2892 // the JSFunction on which new was invoked initially) | |
| 2893 // ----------------------------------- | |
| 2894 | |
| 2895 CheckSpreadAndPushToStack(masm); | |
| 2872 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2896 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 2873 } | 2897 } |
| 2874 | 2898 |
| 2875 // static | 2899 // static |
| 2876 void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { | 2900 void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { |
| 2877 // ----------- S t a t e ------------- | 2901 // ----------- S t a t e ------------- |
| 2878 // -- r1 : requested object size (untagged) | 2902 // -- r1 : requested object size (untagged) |
| 2879 // -- lr : return address | 2903 // -- lr : return address |
| 2880 // ----------------------------------- | 2904 // ----------------------------------- |
| 2881 __ SmiTag(r1); | 2905 __ SmiTag(r1); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3030 __ bkpt(0); | 3054 __ bkpt(0); |
| 3031 } | 3055 } |
| 3032 } | 3056 } |
| 3033 | 3057 |
| 3034 #undef __ | 3058 #undef __ |
| 3035 | 3059 |
| 3036 } // namespace internal | 3060 } // namespace internal |
| 3037 } // namespace v8 | 3061 } // namespace v8 |
| 3038 | 3062 |
| 3039 #endif // V8_TARGET_ARCH_ARM | 3063 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |