OLD | NEW |
---|---|
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 11 matching lines...) Expand all Loading... | |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #if defined(V8_TARGET_ARCH_IA32) | 30 #if defined(V8_TARGET_ARCH_IA32) |
31 | 31 |
32 #include "code-stubs-ia32.h" | |
32 #include "codegen-inl.h" | 33 #include "codegen-inl.h" |
33 | 34 |
34 namespace v8 { | 35 namespace v8 { |
35 namespace internal { | 36 namespace internal { |
36 | 37 |
37 | 38 |
38 #define __ ACCESS_MASM(masm) | 39 #define __ ACCESS_MASM(masm) |
39 | 40 |
40 | 41 |
41 void Builtins::Generate_Adaptor(MacroAssembler* masm, | 42 void Builtins::Generate_Adaptor(MacroAssembler* masm, |
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
688 ParameterCount actual(eax); | 689 ParameterCount actual(eax); |
689 __ SmiUntag(eax); | 690 __ SmiUntag(eax); |
690 __ mov(edi, Operand(ebp, 4 * kPointerSize)); | 691 __ mov(edi, Operand(ebp, 4 * kPointerSize)); |
691 __ InvokeFunction(edi, actual, CALL_FUNCTION); | 692 __ InvokeFunction(edi, actual, CALL_FUNCTION); |
692 | 693 |
693 __ LeaveInternalFrame(); | 694 __ LeaveInternalFrame(); |
694 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 695 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
695 } | 696 } |
696 | 697 |
697 | 698 |
698 // Load the built-in Array function from the current context. | |
699 static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { | |
700 // Load the global context. | |
701 __ mov(result, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | |
702 __ mov(result, FieldOperand(result, GlobalObject::kGlobalContextOffset)); | |
703 // Load the Array function from the global context. | |
704 __ mov(result, | |
705 Operand(result, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | |
706 } | |
707 | |
708 | |
709 // Number of empty elements to allocate for an empty array. | 699 // Number of empty elements to allocate for an empty array. |
710 static const int kPreallocatedArrayElements = 4; | 700 static const int kPreallocatedArrayElements = 4; |
711 | 701 |
712 | 702 |
713 // Allocate an empty JSArray. The allocated array is put into the result | 703 // Allocate an empty JSArray. The allocated array is put into the result |
714 // register. If the parameter initial_capacity is larger than zero an elements | 704 // register. If the parameter initial_capacity is larger than zero an elements |
715 // backing store is allocated with this size and filled with the hole values. | 705 // backing store is allocated with this size and filled with the hole values. |
716 // Otherwise the elements backing store is set to the empty FixedArray. | 706 // Otherwise the elements backing store is set to the empty FixedArray. |
717 static void AllocateEmptyJSArray(MacroAssembler* masm, | 707 static void AllocateEmptyJSArray(MacroAssembler* masm, |
718 Register array_function, | 708 Register array_function, |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1088 | 1078 |
1089 void Builtins::Generate_ArrayCode(MacroAssembler* masm) { | 1079 void Builtins::Generate_ArrayCode(MacroAssembler* masm) { |
1090 // ----------- S t a t e ------------- | 1080 // ----------- S t a t e ------------- |
1091 // -- eax : argc | 1081 // -- eax : argc |
1092 // -- esp[0] : return address | 1082 // -- esp[0] : return address |
1093 // -- esp[4] : last argument | 1083 // -- esp[4] : last argument |
1094 // ----------------------------------- | 1084 // ----------------------------------- |
1095 Label generic_array_code; | 1085 Label generic_array_code; |
1096 | 1086 |
1097 // Get the Array function. | 1087 // Get the Array function. |
1098 GenerateLoadArrayFunction(masm, edi); | 1088 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi); |
1099 | 1089 |
1100 if (FLAG_debug_code) { | 1090 if (FLAG_debug_code) { |
1101 // Initial map for the builtin Array function shoud be a map. | 1091 // Initial map for the builtin Array function shoud be a map. |
1102 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 1092 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
1103 // Will both indicate a NULL and a Smi. | 1093 // Will both indicate a NULL and a Smi. |
1104 __ test(ebx, Immediate(kSmiTagMask)); | 1094 __ test(ebx, Immediate(kSmiTagMask)); |
1105 __ Assert(not_zero, "Unexpected initial map for Array function"); | 1095 __ Assert(not_zero, "Unexpected initial map for Array function"); |
1106 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 1096 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
1107 __ Assert(equal, "Unexpected initial map for Array function"); | 1097 __ Assert(equal, "Unexpected initial map for Array function"); |
1108 } | 1098 } |
(...skipping 15 matching lines...) Expand all Loading... | |
1124 // -- eax : argc | 1114 // -- eax : argc |
1125 // -- edi : constructor | 1115 // -- edi : constructor |
1126 // -- esp[0] : return address | 1116 // -- esp[0] : return address |
1127 // -- esp[4] : last argument | 1117 // -- esp[4] : last argument |
1128 // ----------------------------------- | 1118 // ----------------------------------- |
1129 Label generic_constructor; | 1119 Label generic_constructor; |
1130 | 1120 |
1131 if (FLAG_debug_code) { | 1121 if (FLAG_debug_code) { |
1132 // The array construct code is only set for the builtin Array function which | 1122 // The array construct code is only set for the builtin Array function which |
1133 // does always have a map. | 1123 // does always have a map. |
1134 GenerateLoadArrayFunction(masm, ebx); | 1124 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ebx); |
1135 __ cmp(edi, Operand(ebx)); | 1125 __ cmp(edi, Operand(ebx)); |
1136 __ Assert(equal, "Unexpected Array function"); | 1126 __ Assert(equal, "Unexpected Array function"); |
1137 // Initial map for the builtin Array function should be a map. | 1127 // Initial map for the builtin Array function should be a map. |
1138 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 1128 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
1139 // Will both indicate a NULL and a Smi. | 1129 // Will both indicate a NULL and a Smi. |
1140 __ test(ebx, Immediate(kSmiTagMask)); | 1130 __ test(ebx, Immediate(kSmiTagMask)); |
1141 __ Assert(not_zero, "Unexpected initial map for Array function"); | 1131 __ Assert(not_zero, "Unexpected initial map for Array function"); |
1142 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 1132 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
1143 __ Assert(equal, "Unexpected initial map for Array function"); | 1133 __ Assert(equal, "Unexpected initial map for Array function"); |
1144 } | 1134 } |
1145 | 1135 |
1146 // Run the native code for the Array function called as constructor. | 1136 // Run the native code for the Array function called as constructor. |
1147 ArrayNativeCode(masm, true, &generic_constructor); | 1137 ArrayNativeCode(masm, true, &generic_constructor); |
1148 | 1138 |
1149 // Jump to the generic construct code in case the specialized code cannot | 1139 // Jump to the generic construct code in case the specialized code cannot |
1150 // handle the construction. | 1140 // handle the construction. |
1151 __ bind(&generic_constructor); | 1141 __ bind(&generic_constructor); |
1152 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); | 1142 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); |
1153 Handle<Code> generic_construct_stub(code); | 1143 Handle<Code> generic_construct_stub(code); |
1154 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 1144 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
1155 } | 1145 } |
1156 | 1146 |
1157 | 1147 |
1148 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | |
1149 // ----------- S t a t e ------------- | |
1150 // -- eax : number of arguments | |
1151 // -- edi : constructor function | |
1152 // -- esp[0] : return address | |
1153 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
1154 // -- esp[(argc + 1) * 4] : receiver | |
1155 // ----------------------------------- | |
1156 __ IncrementCounter(&Counters::string_ctor_calls, 1); | |
1157 | |
1158 if (FLAG_debug_code) { | |
1159 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx); | |
1160 __ cmp(edi, Operand(ecx)); | |
1161 __ Assert(equal, "Unexpected String function"); | |
1162 } | |
1163 | |
1164 // Load the first argument and get rid of the rest (including the | |
1165 // receiver). | |
1166 Label no_arguments; | |
1167 __ test(eax, Operand(eax)); | |
1168 __ j(zero, &no_arguments); | |
1169 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); | |
1170 __ pop(ecx); | |
1171 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | |
1172 __ push(ecx); | |
1173 __ mov(eax, ebx); | |
1174 | |
1175 // Lookup the argument in the number to string cache. | |
1176 Label not_cached, argument_is_string; | |
1177 NumberToStringStub::GenerateLookupNumberStringCache( | |
1178 masm, | |
1179 eax, // Input. | |
1180 ebx, // Result. | |
1181 ecx, // Scratch 1. | |
1182 edx, // Scratch 2. | |
1183 false, // Input is known to be smi? | |
1184 ¬_cached); | |
1185 __ IncrementCounter(&Counters::string_ctor_cached_number, 1); | |
1186 __ bind(&argument_is_string); | |
1187 // ----------- S t a t e ------------- | |
1188 // -- ebx : argument converted to string | |
1189 // -- edi : constructor function | |
1190 // -- esp[0] : return address | |
1191 // ----------------------------------- | |
1192 | |
1193 // Allocate a JSValue and put the tagged pointer into eax. | |
1194 Label gc_required; | |
1195 __ AllocateInNewSpace(JSValue::kSize, | |
1196 eax, // Result. | |
1197 ecx, // New allocation top (we ignore it). | |
1198 no_reg, | |
1199 &gc_required, | |
1200 TAG_OBJECT); | |
1201 | |
1202 // Set the map. | |
1203 __ LoadGlobalFunctionInitialMap(edi, ecx); | |
antonm
2010/08/26 13:51:16
maybe add a check under FLAG_debug_code above this
| |
1204 if (FLAG_debug_code) { | |
1205 __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset), | |
1206 JSValue::kSize >> kPointerSizeLog2); | |
1207 __ Assert(equal, "Unexpected string wrapper instance size"); | |
1208 __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0); | |
1209 __ Assert(equal, "Unexpected unused properties of string wrapper"); | |
1210 } | |
1211 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); | |
1212 | |
1213 // Set properties and elements. | |
1214 __ Set(ecx, Immediate(Factory::empty_fixed_array())); | |
1215 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); | |
1216 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx); | |
1217 | |
1218 // Set the value. | |
1219 __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); | |
1220 | |
1221 // Ensure the object is fully initialized. | |
1222 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); | |
1223 | |
1224 // We're done. Return. | |
1225 __ ret(0); | |
1226 | |
1227 // The argument was not found in the number to string cache. Check | |
1228 // if it's a string already before calling the conversion builtin. | |
1229 Label convert_argument; | |
1230 __ bind(¬_cached); | |
1231 STATIC_ASSERT(kSmiTag == 0); | |
1232 __ test(eax, Immediate(kSmiTagMask)); | |
1233 __ j(zero, &convert_argument); | |
1234 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); | |
1235 __ j(NegateCondition(is_string), &convert_argument); | |
1236 __ mov(ebx, eax); | |
1237 __ IncrementCounter(&Counters::string_ctor_string_value, 1); | |
1238 __ jmp(&argument_is_string); | |
1239 | |
1240 // Invoke the conversion builtin and put the result into ebx. | |
1241 __ bind(&convert_argument); | |
1242 __ IncrementCounter(&Counters::string_ctor_conversions, 1); | |
1243 __ EnterInternalFrame(); | |
1244 __ push(edi); // Preserve the function. | |
1245 __ push(eax); | |
1246 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); | |
1247 __ pop(edi); | |
1248 __ LeaveInternalFrame(); | |
1249 __ mov(ebx, eax); | |
1250 __ jmp(&argument_is_string); | |
1251 | |
1252 // Load the empty string into ebx, remove the receiver from the | |
1253 // stack, and jump back to the case where the argument is a string. | |
1254 __ bind(&no_arguments); | |
1255 __ Set(ebx, Immediate(Factory::empty_string())); | |
1256 __ pop(ecx); | |
1257 __ lea(esp, Operand(esp, kPointerSize)); | |
1258 __ push(ecx); | |
1259 __ jmp(&argument_is_string); | |
1260 | |
1261 // At this point the argument is already a string. Call runtime to | |
1262 // create a string wrapper. | |
1263 __ bind(&gc_required); | |
1264 __ IncrementCounter(&Counters::string_ctor_gc_required, 1); | |
1265 __ EnterInternalFrame(); | |
1266 __ push(ebx); | |
1267 __ CallRuntime(Runtime::kNewStringWrapper, 1); | |
1268 __ LeaveInternalFrame(); | |
1269 __ ret(0); | |
1270 } | |
1271 | |
1272 | |
1158 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { | 1273 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
1159 __ push(ebp); | 1274 __ push(ebp); |
1160 __ mov(ebp, Operand(esp)); | 1275 __ mov(ebp, Operand(esp)); |
1161 | 1276 |
1162 // Store the arguments adaptor context sentinel. | 1277 // Store the arguments adaptor context sentinel. |
1163 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1278 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
1164 | 1279 |
1165 // Push the function on the stack. | 1280 // Push the function on the stack. |
1166 __ push(edi); | 1281 __ push(edi); |
1167 | 1282 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1267 __ bind(&dont_adapt_arguments); | 1382 __ bind(&dont_adapt_arguments); |
1268 __ jmp(Operand(edx)); | 1383 __ jmp(Operand(edx)); |
1269 } | 1384 } |
1270 | 1385 |
1271 | 1386 |
1272 #undef __ | 1387 #undef __ |
1273 | 1388 |
1274 } } // namespace v8::internal | 1389 } } // namespace v8::internal |
1275 | 1390 |
1276 #endif // V8_TARGET_ARCH_IA32 | 1391 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |