| 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_IA32 | 5 #if V8_TARGET_ARCH_IA32 | 
| 6 | 6 | 
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" | 
| 8 #include "src/codegen.h" | 8 #include "src/codegen.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 939 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 950     __ j(not_sign, &loop);  // While non-negative (to copy return address). | 950     __ j(not_sign, &loop);  // While non-negative (to copy return address). | 
| 951     __ pop(ebx);            // Discard copy of return address. | 951     __ pop(ebx);            // Discard copy of return address. | 
| 952     __ dec(eax);  // One fewer argument (first argument is new receiver). | 952     __ dec(eax);  // One fewer argument (first argument is new receiver). | 
| 953   } | 953   } | 
| 954 | 954 | 
| 955   // 4. Call the callable. | 955   // 4. Call the callable. | 
| 956   __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 956   __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 
| 957 } | 957 } | 
| 958 | 958 | 
| 959 | 959 | 
|  | 960 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 
|  | 961                                           const int vectorOffset, | 
|  | 962                                           const int argumentsOffset, | 
|  | 963                                           const int indexOffset, | 
|  | 964                                           const int limitOffset) { | 
|  | 965   // Copy all arguments from the array to the stack. | 
|  | 966   Label entry, loop; | 
|  | 967   Register receiver = LoadDescriptor::ReceiverRegister(); | 
|  | 968   Register key = LoadDescriptor::NameRegister(); | 
|  | 969   Register slot = LoadDescriptor::SlotRegister(); | 
|  | 970   Register vector = LoadWithVectorDescriptor::VectorRegister(); | 
|  | 971   __ mov(key, Operand(ebp, indexOffset)); | 
|  | 972   __ jmp(&entry); | 
|  | 973   __ bind(&loop); | 
|  | 974   __ mov(receiver, Operand(ebp, argumentsOffset));  // load arguments | 
|  | 975 | 
|  | 976   // Use inline caching to speed up access to arguments. | 
|  | 977   int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); | 
|  | 978   __ mov(slot, Immediate(Smi::FromInt(slot_index))); | 
|  | 979   __ mov(vector, Operand(ebp, vectorOffset)); | 
|  | 980   Handle<Code> ic = | 
|  | 981       KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); | 
|  | 982   __ call(ic, RelocInfo::CODE_TARGET); | 
|  | 983   // It is important that we do not have a test instruction after the | 
|  | 984   // call.  A test instruction after the call is used to indicate that | 
|  | 985   // we have generated an inline version of the keyed load.  In this | 
|  | 986   // case, we know that we are not generating a test instruction next. | 
|  | 987 | 
|  | 988   // Push the nth argument. | 
|  | 989   __ push(eax); | 
|  | 990 | 
|  | 991   // Update the index on the stack and in register key. | 
|  | 992   __ mov(key, Operand(ebp, indexOffset)); | 
|  | 993   __ add(key, Immediate(1 << kSmiTagSize)); | 
|  | 994   __ mov(Operand(ebp, indexOffset), key); | 
|  | 995 | 
|  | 996   __ bind(&entry); | 
|  | 997   __ cmp(key, Operand(ebp, limitOffset)); | 
|  | 998   __ j(not_equal, &loop); | 
|  | 999 | 
|  | 1000   // On exit, the pushed arguments count is in eax, untagged | 
|  | 1001   __ Move(eax, key); | 
|  | 1002   __ SmiUntag(eax); | 
|  | 1003 } | 
|  | 1004 | 
|  | 1005 | 
|  | 1006 // Used by FunctionApply and ReflectApply | 
|  | 1007 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { | 
|  | 1008   const int kFormalParameters = targetIsArgument ? 3 : 2; | 
|  | 1009   const int kStackSize = kFormalParameters + 1; | 
|  | 1010 | 
|  | 1011   // Stack at entry: | 
|  | 1012   // esp     : return address | 
|  | 1013   // esp[4]  : arguments | 
|  | 1014   // esp[8]  : receiver ("this") | 
|  | 1015   // esp[12] : function | 
|  | 1016   { | 
|  | 1017     FrameScope frame_scope(masm, StackFrame::INTERNAL); | 
|  | 1018     // Stack frame: | 
|  | 1019     // ebp     : Old base pointer | 
|  | 1020     // ebp[4]  : return address | 
|  | 1021     // ebp[8]  : function arguments | 
|  | 1022     // ebp[12] : receiver | 
|  | 1023     // ebp[16] : function | 
|  | 1024     static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; | 
|  | 1025     static const int kReceiverOffset = kArgumentsOffset + kPointerSize; | 
|  | 1026     static const int kFunctionOffset = kReceiverOffset + kPointerSize; | 
|  | 1027     static const int kVectorOffset = | 
|  | 1028         InternalFrameConstants::kCodeOffset - 1 * kPointerSize; | 
|  | 1029 | 
|  | 1030     // Push the vector. | 
|  | 1031     __ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 
|  | 1032     __ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset)); | 
|  | 1033     __ push(edi); | 
|  | 1034 | 
|  | 1035     __ push(Operand(ebp, kFunctionOffset));   // push this | 
|  | 1036     __ push(Operand(ebp, kArgumentsOffset));  // push arguments | 
|  | 1037     if (targetIsArgument) { | 
|  | 1038       __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, | 
|  | 1039                        CALL_FUNCTION); | 
|  | 1040     } else { | 
|  | 1041       __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); | 
|  | 1042     } | 
|  | 1043 | 
|  | 1044     Generate_CheckStackOverflow(masm, kEaxIsSmiTagged); | 
|  | 1045 | 
|  | 1046     // Push current index and limit. | 
|  | 1047     const int kLimitOffset = kVectorOffset - 1 * kPointerSize; | 
|  | 1048     const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 
|  | 1049     __ Push(eax);                            // limit | 
|  | 1050     __ Push(Immediate(0));                   // index | 
|  | 1051     __ Push(Operand(ebp, kReceiverOffset));  // receiver | 
|  | 1052 | 
|  | 1053     // Loop over the arguments array, pushing each value to the stack | 
|  | 1054     Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, | 
|  | 1055                                   kIndexOffset, kLimitOffset); | 
|  | 1056 | 
|  | 1057     // Call the callable. | 
|  | 1058     // TODO(bmeurer): This should be a tail call according to ES6. | 
|  | 1059     __ mov(edi, Operand(ebp, kFunctionOffset)); | 
|  | 1060     __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 
|  | 1061 | 
|  | 1062     // Leave internal frame. | 
|  | 1063   } | 
|  | 1064   __ ret(kStackSize * kPointerSize);  // remove this, receiver, and arguments | 
|  | 1065 } | 
|  | 1066 | 
|  | 1067 | 
|  | 1068 // Used by ReflectConstruct | 
|  | 1069 static void Generate_ConstructHelper(MacroAssembler* masm) { | 
|  | 1070   const int kFormalParameters = 3; | 
|  | 1071   const int kStackSize = kFormalParameters + 1; | 
|  | 1072 | 
|  | 1073   // Stack at entry: | 
|  | 1074   // esp     : return address | 
|  | 1075   // esp[4]  : new target | 
|  | 1076   // esp[8]  : arguments | 
|  | 1077   // esp[16] : constructor | 
|  | 1078   { | 
|  | 1079     FrameScope frame_scope(masm, StackFrame::INTERNAL); | 
|  | 1080     // Stack frame: | 
|  | 1081     // ebp     : Old base pointer | 
|  | 1082     // ebp[4]  : return address | 
|  | 1083     // ebp[8]  : new target | 
|  | 1084     // ebp[12] : arguments | 
|  | 1085     // ebp[16] : constructor | 
|  | 1086     static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; | 
|  | 1087     static const int kArgumentsOffset = kNewTargetOffset + kPointerSize; | 
|  | 1088     static const int kFunctionOffset = kArgumentsOffset + kPointerSize; | 
|  | 1089     static const int kVectorOffset = | 
|  | 1090         InternalFrameConstants::kCodeOffset - 1 * kPointerSize; | 
|  | 1091 | 
|  | 1092     // Push the vector. | 
|  | 1093     __ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 
|  | 1094     __ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset)); | 
|  | 1095     __ push(edi); | 
|  | 1096 | 
|  | 1097     // If newTarget is not supplied, set it to constructor | 
|  | 1098     Label validate_arguments; | 
|  | 1099     __ mov(eax, Operand(ebp, kNewTargetOffset)); | 
|  | 1100     __ CompareRoot(eax, Heap::kUndefinedValueRootIndex); | 
|  | 1101     __ j(not_equal, &validate_arguments, Label::kNear); | 
|  | 1102     __ mov(eax, Operand(ebp, kFunctionOffset)); | 
|  | 1103     __ mov(Operand(ebp, kNewTargetOffset), eax); | 
|  | 1104 | 
|  | 1105     // Validate arguments | 
|  | 1106     __ bind(&validate_arguments); | 
|  | 1107     __ push(Operand(ebp, kFunctionOffset)); | 
|  | 1108     __ push(Operand(ebp, kArgumentsOffset)); | 
|  | 1109     __ push(Operand(ebp, kNewTargetOffset)); | 
|  | 1110     __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, | 
|  | 1111                      CALL_FUNCTION); | 
|  | 1112 | 
|  | 1113     Generate_CheckStackOverflow(masm, kEaxIsSmiTagged); | 
|  | 1114 | 
|  | 1115     // Push current index and limit. | 
|  | 1116     const int kLimitOffset = kVectorOffset - 1 * kPointerSize; | 
|  | 1117     const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 
|  | 1118     __ Push(eax);  // limit | 
|  | 1119     __ push(Immediate(0));  // index | 
|  | 1120     // Push the constructor function as callee. | 
|  | 1121     __ push(Operand(ebp, kFunctionOffset)); | 
|  | 1122 | 
|  | 1123     // Loop over the arguments array, pushing each value to the stack | 
|  | 1124     Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, | 
|  | 1125                                   kIndexOffset, kLimitOffset); | 
|  | 1126 | 
|  | 1127     // Use undefined feedback vector | 
|  | 1128     __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); | 
|  | 1129     __ mov(edi, Operand(ebp, kFunctionOffset)); | 
|  | 1130     __ mov(edx, Operand(ebp, kNewTargetOffset)); | 
|  | 1131 | 
|  | 1132     // Call the function. | 
|  | 1133     __ Call(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 
|  | 1134 | 
|  | 1135     // Leave internal frame. | 
|  | 1136   } | 
|  | 1137   // remove this, target, arguments, and newTarget | 
|  | 1138   __ ret(kStackSize * kPointerSize); | 
|  | 1139 } | 
|  | 1140 | 
|  | 1141 | 
| 960 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1142 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 
| 961   // ----------- S t a t e ------------- | 1143   Generate_ApplyHelper(masm, false); | 
| 962   //  -- eax     : argc |  | 
| 963   //  -- esp[0]  : return address |  | 
| 964   //  -- esp[4]  : argArray |  | 
| 965   //  -- esp[8]  : thisArg |  | 
| 966   //  -- esp[12] : receiver |  | 
| 967   // ----------------------------------- |  | 
| 968 |  | 
| 969   // 1. Load receiver into edi, argArray into eax (if present), remove all |  | 
| 970   // arguments from the stack (including the receiver), and push thisArg (if |  | 
| 971   // present) instead. |  | 
| 972   { |  | 
| 973     Label no_arg_array, no_this_arg; |  | 
| 974     __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); |  | 
| 975     __ mov(ebx, edx); |  | 
| 976     __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); |  | 
| 977     __ test(eax, eax); |  | 
| 978     __ j(zero, &no_this_arg, Label::kNear); |  | 
| 979     { |  | 
| 980       __ mov(edx, Operand(esp, eax, times_pointer_size, 0)); |  | 
| 981       __ cmp(eax, Immediate(1)); |  | 
| 982       __ j(equal, &no_arg_array, Label::kNear); |  | 
| 983       __ mov(ebx, Operand(esp, eax, times_pointer_size, -kPointerSize)); |  | 
| 984       __ bind(&no_arg_array); |  | 
| 985     } |  | 
| 986     __ bind(&no_this_arg); |  | 
| 987     __ PopReturnAddressTo(ecx); |  | 
| 988     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); |  | 
| 989     __ Push(edx); |  | 
| 990     __ PushReturnAddressFrom(ecx); |  | 
| 991     __ Move(eax, ebx); |  | 
| 992   } |  | 
| 993 |  | 
| 994   // ----------- S t a t e ------------- |  | 
| 995   //  -- eax    : argArray |  | 
| 996   //  -- edi    : receiver |  | 
| 997   //  -- esp[0] : return address |  | 
| 998   //  -- esp[4] : thisArg |  | 
| 999   // ----------------------------------- |  | 
| 1000 |  | 
| 1001   // 2. Make sure the receiver is actually callable. |  | 
| 1002   Label receiver_not_callable; |  | 
| 1003   __ JumpIfSmi(edi, &receiver_not_callable, Label::kNear); |  | 
| 1004   __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |  | 
| 1005   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable); |  | 
| 1006   __ j(zero, &receiver_not_callable, Label::kNear); |  | 
| 1007 |  | 
| 1008   // 3. Tail call with no arguments if argArray is null or undefined. |  | 
| 1009   Label no_arguments; |  | 
| 1010   __ JumpIfRoot(eax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); |  | 
| 1011   __ JumpIfRoot(eax, Heap::kUndefinedValueRootIndex, &no_arguments, |  | 
| 1012                 Label::kNear); |  | 
| 1013 |  | 
| 1014   // 4a. Apply the receiver to the given argArray (passing undefined for |  | 
| 1015   // new.target). |  | 
| 1016   __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); |  | 
| 1017   __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |  | 
| 1018 |  | 
| 1019   // 4b. The argArray is either null or undefined, so we tail call without any |  | 
| 1020   // arguments to the receiver. |  | 
| 1021   __ bind(&no_arguments); |  | 
| 1022   { |  | 
| 1023     __ Set(eax, 0); |  | 
| 1024     __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |  | 
| 1025   } |  | 
| 1026 |  | 
| 1027   // 4c. The receiver is not callable, throw an appropriate TypeError. |  | 
| 1028   __ bind(&receiver_not_callable); |  | 
| 1029   { |  | 
| 1030     __ mov(Operand(esp, kPointerSize), edi); |  | 
| 1031     __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1); |  | 
| 1032   } |  | 
| 1033 } | 1144 } | 
| 1034 | 1145 | 
| 1035 | 1146 | 
| 1036 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 1147 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 
| 1037   // ----------- S t a t e ------------- | 1148   Generate_ApplyHelper(masm, true); | 
| 1038   //  -- eax     : argc |  | 
| 1039   //  -- esp[0]  : return address |  | 
| 1040   //  -- esp[4]  : argumentsList |  | 
| 1041   //  -- esp[8]  : thisArgument |  | 
| 1042   //  -- esp[12] : target |  | 
| 1043   //  -- esp[16] : receiver |  | 
| 1044   // ----------------------------------- |  | 
| 1045 |  | 
| 1046   // 1. Load target into edi (if present), argumentsList into eax (if present), |  | 
| 1047   // remove all arguments from the stack (including the receiver), and push |  | 
| 1048   // thisArgument (if present) instead. |  | 
| 1049   { |  | 
| 1050     Label done; |  | 
| 1051     __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); |  | 
| 1052     __ mov(edx, edi); |  | 
| 1053     __ mov(ebx, edi); |  | 
| 1054     __ cmp(eax, Immediate(1)); |  | 
| 1055     __ j(below, &done, Label::kNear); |  | 
| 1056     __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); |  | 
| 1057     __ j(equal, &done, Label::kNear); |  | 
| 1058     __ mov(edx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); |  | 
| 1059     __ cmp(eax, Immediate(3)); |  | 
| 1060     __ j(below, &done, Label::kNear); |  | 
| 1061     __ mov(ebx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); |  | 
| 1062     __ bind(&done); |  | 
| 1063     __ PopReturnAddressTo(ecx); |  | 
| 1064     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); |  | 
| 1065     __ Push(edx); |  | 
| 1066     __ PushReturnAddressFrom(ecx); |  | 
| 1067     __ Move(eax, ebx); |  | 
| 1068   } |  | 
| 1069 |  | 
| 1070   // ----------- S t a t e ------------- |  | 
| 1071   //  -- eax    : argumentsList |  | 
| 1072   //  -- edi    : target |  | 
| 1073   //  -- esp[0] : return address |  | 
| 1074   //  -- esp[4] : thisArgument |  | 
| 1075   // ----------------------------------- |  | 
| 1076 |  | 
| 1077   // 2. Make sure the target is actually callable. |  | 
| 1078   Label target_not_callable; |  | 
| 1079   __ JumpIfSmi(edi, &target_not_callable, Label::kNear); |  | 
| 1080   __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |  | 
| 1081   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable); |  | 
| 1082   __ j(zero, &target_not_callable, Label::kNear); |  | 
| 1083 |  | 
| 1084   // 3a. Apply the target to the given argumentsList (passing undefined for |  | 
| 1085   // new.target). |  | 
| 1086   __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); |  | 
| 1087   __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |  | 
| 1088 |  | 
| 1089   // 3b. The target is not callable, throw an appropriate TypeError. |  | 
| 1090   __ bind(&target_not_callable); |  | 
| 1091   { |  | 
| 1092     __ mov(Operand(esp, kPointerSize), edi); |  | 
| 1093     __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1); |  | 
| 1094   } |  | 
| 1095 } | 1149 } | 
| 1096 | 1150 | 
| 1097 | 1151 | 
| 1098 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 1152 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 
| 1099   // ----------- S t a t e ------------- | 1153   Generate_ConstructHelper(masm); | 
| 1100   //  -- eax     : argc | 1154 } | 
| 1101   //  -- esp[0]  : return address | 1155 | 
| 1102   //  -- esp[4]  : new.target (optional) | 1156 | 
| 1103   //  -- esp[8]  : argumentsList |  | 
| 1104   //  -- esp[12] : target |  | 
| 1105   //  -- esp[16] : receiver |  | 
| 1106   // ----------------------------------- |  | 
| 1107 |  | 
| 1108   // 1. Load target into edi (if present), argumentsList into eax (if present), |  | 
| 1109   // new.target into edx (if present, otherwise use target), remove all |  | 
| 1110   // arguments from the stack (including the receiver), and push thisArgument |  | 
| 1111   // (if present) instead. |  | 
| 1112   { |  | 
| 1113     Label done; |  | 
| 1114     __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); |  | 
| 1115     __ mov(edx, edi); |  | 
| 1116     __ mov(ebx, edi); |  | 
| 1117     __ cmp(eax, Immediate(1)); |  | 
| 1118     __ j(below, &done, Label::kNear); |  | 
| 1119     __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); |  | 
| 1120     __ mov(edx, edi); |  | 
| 1121     __ j(equal, &done, Label::kNear); |  | 
| 1122     __ mov(ebx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); |  | 
| 1123     __ cmp(eax, Immediate(3)); |  | 
| 1124     __ j(below, &done, Label::kNear); |  | 
| 1125     __ mov(edx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); |  | 
| 1126     __ bind(&done); |  | 
| 1127     __ PopReturnAddressTo(ecx); |  | 
| 1128     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); |  | 
| 1129     __ PushRoot(Heap::kUndefinedValueRootIndex); |  | 
| 1130     __ PushReturnAddressFrom(ecx); |  | 
| 1131     __ Move(eax, ebx); |  | 
| 1132   } |  | 
| 1133 |  | 
| 1134   // ----------- S t a t e ------------- |  | 
| 1135   //  -- eax    : argumentsList |  | 
| 1136   //  -- edx    : new.target |  | 
| 1137   //  -- edi    : target |  | 
| 1138   //  -- esp[0] : return address |  | 
| 1139   //  -- esp[4] : receiver (undefined) |  | 
| 1140   // ----------------------------------- |  | 
| 1141 |  | 
| 1142   // 2. Make sure the target is actually a constructor. |  | 
| 1143   Label target_not_constructor; |  | 
| 1144   __ JumpIfSmi(edi, &target_not_constructor, Label::kNear); |  | 
| 1145   __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |  | 
| 1146   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor); |  | 
| 1147   __ j(zero, &target_not_constructor, Label::kNear); |  | 
| 1148 |  | 
| 1149   // 3. Make sure the target is actually a constructor. |  | 
| 1150   Label new_target_not_constructor; |  | 
| 1151   __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear); |  | 
| 1152   __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |  | 
| 1153   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor); |  | 
| 1154   __ j(zero, &new_target_not_constructor, Label::kNear); |  | 
| 1155 |  | 
| 1156   // 4a. Construct the target with the given new.target and argumentsList. |  | 
| 1157   __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |  | 
| 1158 |  | 
| 1159   // 4b. The target is not a constructor, throw an appropriate TypeError. |  | 
| 1160   __ bind(&target_not_constructor); |  | 
| 1161   { |  | 
| 1162     __ mov(Operand(esp, kPointerSize), edi); |  | 
| 1163     __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1); |  | 
| 1164   } |  | 
| 1165 |  | 
| 1166   // 4c. The new.target is not a constructor, throw an appropriate TypeError. |  | 
| 1167   __ bind(&new_target_not_constructor); |  | 
| 1168   { |  | 
| 1169     __ mov(Operand(esp, kPointerSize), edx); |  | 
| 1170     __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1); |  | 
| 1171   } |  | 
| 1172 } |  | 
| 1173 |  | 
| 1174 |  | 
| 1175 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { | 1157 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { | 
| 1176   // ----------- S t a t e ------------- | 1158   // ----------- S t a t e ------------- | 
| 1177   //  -- eax : argc | 1159   //  -- eax : argc | 
| 1178   //  -- esp[0] : return address | 1160   //  -- esp[0] : return address | 
| 1179   //  -- esp[4] : last argument | 1161   //  -- esp[4] : last argument | 
| 1180   // ----------------------------------- | 1162   // ----------------------------------- | 
| 1181   Label generic_array_code; | 1163   Label generic_array_code; | 
| 1182 | 1164 | 
| 1183   // Get the InternalArray function. | 1165   // Get the InternalArray function. | 
| 1184   __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); | 1166   __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); | 
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1433   __ leave(); | 1415   __ leave(); | 
| 1434 | 1416 | 
| 1435   // Remove caller arguments from the stack. | 1417   // Remove caller arguments from the stack. | 
| 1436   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 1418   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 
| 1437   __ pop(ecx); | 1419   __ pop(ecx); | 
| 1438   __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver | 1420   __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver | 
| 1439   __ push(ecx); | 1421   __ push(ecx); | 
| 1440 } | 1422 } | 
| 1441 | 1423 | 
| 1442 | 1424 | 
| 1443 // static |  | 
| 1444 void Builtins::Generate_Apply(MacroAssembler* masm) { |  | 
| 1445   // ----------- S t a t e ------------- |  | 
| 1446   //  -- eax    : argumentsList |  | 
| 1447   //  -- edi    : target |  | 
| 1448   //  -- edx    : new.target (checked to be constructor or undefined) |  | 
| 1449   //  -- esp[0] : return address. |  | 
| 1450   //  -- esp[4] : thisArgument |  | 
| 1451   // ----------------------------------- |  | 
| 1452 |  | 
| 1453   // Create the list of arguments from the array-like argumentsList. |  | 
| 1454   { |  | 
| 1455     Label create_arguments, create_array, create_runtime, done_create; |  | 
| 1456     __ JumpIfSmi(eax, &create_runtime); |  | 
| 1457 |  | 
| 1458     // Load the map of argumentsList into ecx. |  | 
| 1459     __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |  | 
| 1460 |  | 
| 1461     // Load native context into ebx. |  | 
| 1462     __ mov(ebx, NativeContextOperand()); |  | 
| 1463 |  | 
| 1464     // Check if argumentsList is an (unmodified) arguments object. |  | 
| 1465     __ cmp(ecx, ContextOperand(ebx, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); |  | 
| 1466     __ j(equal, &create_arguments); |  | 
| 1467     __ cmp(ecx, ContextOperand(ebx, Context::STRICT_ARGUMENTS_MAP_INDEX)); |  | 
| 1468     __ j(equal, &create_arguments); |  | 
| 1469 |  | 
| 1470     // Check if argumentsList is a fast JSArray. |  | 
| 1471     __ CmpInstanceType(ecx, JS_ARRAY_TYPE); |  | 
| 1472     __ j(equal, &create_array); |  | 
| 1473 |  | 
| 1474     // Ask the runtime to create the list (actually a FixedArray). |  | 
| 1475     __ bind(&create_runtime); |  | 
| 1476     { |  | 
| 1477       FrameScope scope(masm, StackFrame::INTERNAL); |  | 
| 1478       __ Push(edi); |  | 
| 1479       __ Push(edx); |  | 
| 1480       __ Push(eax); |  | 
| 1481       __ CallRuntime(Runtime::kCreateListFromArrayLike, 1); |  | 
| 1482       __ Pop(edx); |  | 
| 1483       __ Pop(edi); |  | 
| 1484       __ mov(ebx, FieldOperand(eax, FixedArray::kLengthOffset)); |  | 
| 1485       __ SmiUntag(ebx); |  | 
| 1486     } |  | 
| 1487     __ jmp(&done_create); |  | 
| 1488 |  | 
| 1489     // Try to create the list from an arguments object. |  | 
| 1490     __ bind(&create_arguments); |  | 
| 1491     __ mov(ebx, |  | 
| 1492            FieldOperand(eax, JSObject::kHeaderSize + |  | 
| 1493                                  Heap::kArgumentsLengthIndex * kPointerSize)); |  | 
| 1494     __ mov(ecx, FieldOperand(eax, JSObject::kElementsOffset)); |  | 
| 1495     __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); |  | 
| 1496     __ j(not_equal, &create_runtime); |  | 
| 1497     __ SmiUntag(ebx); |  | 
| 1498     __ mov(eax, ecx); |  | 
| 1499     __ jmp(&done_create); |  | 
| 1500 |  | 
| 1501     // Try to create the list from a JSArray object. |  | 
| 1502     __ bind(&create_array); |  | 
| 1503     __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); |  | 
| 1504     __ DecodeField<Map::ElementsKindBits>(ecx); |  | 
| 1505     STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); |  | 
| 1506     STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |  | 
| 1507     STATIC_ASSERT(FAST_ELEMENTS == 2); |  | 
| 1508     __ cmp(ecx, Immediate(FAST_ELEMENTS)); |  | 
| 1509     __ j(above, &create_runtime); |  | 
| 1510     __ cmp(ecx, Immediate(FAST_HOLEY_SMI_ELEMENTS)); |  | 
| 1511     __ j(equal, &create_runtime); |  | 
| 1512     __ mov(ebx, FieldOperand(eax, JSArray::kLengthOffset)); |  | 
| 1513     __ SmiUntag(ebx); |  | 
| 1514     __ mov(eax, FieldOperand(eax, JSArray::kElementsOffset)); |  | 
| 1515 |  | 
| 1516     __ bind(&done_create); |  | 
| 1517   } |  | 
| 1518 |  | 
| 1519   // Check for stack overflow. |  | 
| 1520   { |  | 
| 1521     // Check the stack for overflow. We are not trying to catch interruptions |  | 
| 1522     // (i.e. debug break and preemption) here, so check the "real stack limit". |  | 
| 1523     Label done; |  | 
| 1524     ExternalReference real_stack_limit = |  | 
| 1525         ExternalReference::address_of_real_stack_limit(masm->isolate()); |  | 
| 1526     __ mov(ecx, Operand::StaticVariable(real_stack_limit)); |  | 
| 1527     // Make ecx the space we have left. The stack might already be overflowed |  | 
| 1528     // here which will cause ecx to become negative. |  | 
| 1529     __ neg(ecx); |  | 
| 1530     __ add(ecx, esp); |  | 
| 1531     __ sar(ecx, kPointerSizeLog2); |  | 
| 1532     // Check if the arguments will overflow the stack. |  | 
| 1533     __ cmp(ecx, ebx); |  | 
| 1534     __ j(greater, &done, Label::kNear);  // Signed comparison. |  | 
| 1535     __ TailCallRuntime(Runtime::kThrowStackOverflow, 1, 1); |  | 
| 1536     __ bind(&done); |  | 
| 1537   } |  | 
| 1538 |  | 
| 1539   // ----------- S t a t e ------------- |  | 
| 1540   //  -- edi    : target |  | 
| 1541   //  -- eax    : args (a FixedArray built from argumentsList) |  | 
| 1542   //  -- ebx    : len (number of elements to push from args) |  | 
| 1543   //  -- edx    : new.target (checked to be constructor or undefined) |  | 
| 1544   //  -- esp[0] : return address. |  | 
| 1545   //  -- esp[4] : thisArgument |  | 
| 1546   // ----------------------------------- |  | 
| 1547 |  | 
| 1548   // Push arguments onto the stack (thisArgument is already on the stack). |  | 
| 1549   { |  | 
| 1550     __ movd(xmm0, edx); |  | 
| 1551     __ PopReturnAddressTo(edx); |  | 
| 1552     __ Move(ecx, Immediate(0)); |  | 
| 1553     Label done, loop; |  | 
| 1554     __ bind(&loop); |  | 
| 1555     __ cmp(ecx, ebx); |  | 
| 1556     __ j(equal, &done, Label::kNear); |  | 
| 1557     __ Push( |  | 
| 1558         FieldOperand(eax, ecx, times_pointer_size, FixedArray::kHeaderSize)); |  | 
| 1559     __ inc(ecx); |  | 
| 1560     __ jmp(&loop); |  | 
| 1561     __ bind(&done); |  | 
| 1562     __ PushReturnAddressFrom(edx); |  | 
| 1563     __ movd(edx, xmm0); |  | 
| 1564     __ Move(eax, ebx); |  | 
| 1565   } |  | 
| 1566 |  | 
| 1567   // Dispatch to Call or Construct depending on whether new.target is undefined. |  | 
| 1568   { |  | 
| 1569     __ CompareRoot(edx, Heap::kUndefinedValueRootIndex); |  | 
| 1570     __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |  | 
| 1571     __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |  | 
| 1572   } |  | 
| 1573 } |  | 
| 1574 |  | 
| 1575 |  | 
| 1576 // static | 1425 // static | 
| 1577 void Builtins::Generate_CallFunction(MacroAssembler* masm, | 1426 void Builtins::Generate_CallFunction(MacroAssembler* masm, | 
| 1578                                      ConvertReceiverMode mode) { | 1427                                      ConvertReceiverMode mode) { | 
| 1579   // ----------- S t a t e ------------- | 1428   // ----------- S t a t e ------------- | 
| 1580   //  -- eax : the number of arguments (not including the receiver) | 1429   //  -- eax : the number of arguments (not including the receiver) | 
| 1581   //  -- edi : the function to call (checked to be a JSFunction) | 1430   //  -- edi : the function to call (checked to be a JSFunction) | 
| 1582   // ----------------------------------- | 1431   // ----------------------------------- | 
| 1583   __ AssertFunction(edi); | 1432   __ AssertFunction(edi); | 
| 1584 | 1433 | 
| 1585   // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 1434   // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2131 | 1980 | 
| 2132   __ bind(&ok); | 1981   __ bind(&ok); | 
| 2133   __ ret(0); | 1982   __ ret(0); | 
| 2134 } | 1983 } | 
| 2135 | 1984 | 
| 2136 #undef __ | 1985 #undef __ | 
| 2137 }  // namespace internal | 1986 }  // namespace internal | 
| 2138 }  // namespace v8 | 1987 }  // namespace v8 | 
| 2139 | 1988 | 
| 2140 #endif  // V8_TARGET_ARCH_IA32 | 1989 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW | 
|---|