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 1241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1252 | 1252 |
1253 | 1253 |
1254 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | 1254 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
1255 // ----------- S t a t e ------------- | 1255 // ----------- S t a t e ------------- |
1256 // -- eax : number of arguments | 1256 // -- eax : number of arguments |
1257 // -- edi : constructor function | 1257 // -- edi : constructor function |
1258 // -- esp[0] : return address | 1258 // -- esp[0] : return address |
1259 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1259 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1260 // -- esp[(argc + 1) * 4] : receiver | 1260 // -- esp[(argc + 1) * 4] : receiver |
1261 // ----------------------------------- | 1261 // ----------------------------------- |
1262 Counters* counters = masm->isolate()->counters(); | |
1263 __ IncrementCounter(counters->string_ctor_calls(), 1); | |
1264 | 1262 |
1265 if (FLAG_debug_code) { | 1263 // 1. Load the first argument into ebx and get rid of the rest (including the |
1266 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx); | 1264 // receiver). |
1267 __ cmp(edi, ecx); | 1265 { |
1268 __ Assert(equal, kUnexpectedStringFunction); | 1266 Label no_arguments, done; |
| 1267 __ test(eax, eax); |
| 1268 __ j(zero, &no_arguments, Label::kNear); |
| 1269 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); |
| 1270 __ jmp(&done, Label::kNear); |
| 1271 __ bind(&no_arguments); |
| 1272 __ LoadRoot(ebx, Heap::kempty_stringRootIndex); |
| 1273 __ bind(&done); |
| 1274 __ PopReturnAddressTo(ecx); |
| 1275 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); |
| 1276 __ PushReturnAddressFrom(ecx); |
1269 } | 1277 } |
1270 | 1278 |
1271 // Load the first argument into eax and get rid of the rest | 1279 // 2. Make sure ebx is a string. |
1272 // (including the receiver). | 1280 { |
1273 Label no_arguments; | 1281 Label convert, done_convert; |
1274 __ test(eax, eax); | 1282 __ JumpIfSmi(ebx, &convert, Label::kNear); |
1275 __ j(zero, &no_arguments); | 1283 __ CmpObjectType(ebx, FIRST_NONSTRING_TYPE, edx); |
1276 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); | 1284 __ j(below, &done_convert); |
1277 __ pop(ecx); | 1285 __ bind(&convert); |
1278 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1286 { |
1279 __ push(ecx); | 1287 FrameScope scope(masm, StackFrame::INTERNAL); |
1280 __ mov(eax, ebx); | 1288 ToStringStub stub(masm->isolate()); |
| 1289 __ Push(edi); |
| 1290 __ Move(eax, ebx); |
| 1291 __ CallStub(&stub); |
| 1292 __ Move(ebx, eax); |
| 1293 __ Pop(edi); |
| 1294 } |
| 1295 __ bind(&done_convert); |
| 1296 } |
1281 | 1297 |
1282 // Lookup the argument in the number to string cache. | 1298 // 3. Allocate a JSValue wrapper for the string. |
1283 Label not_cached, argument_is_string; | 1299 { |
1284 __ LookupNumberStringCache(eax, // Input. | 1300 // ----------- S t a t e ------------- |
1285 ebx, // Result. | 1301 // -- ebx : the first argument |
1286 ecx, // Scratch 1. | 1302 // -- edi : constructor function |
1287 edx, // Scratch 2. | 1303 // ----------------------------------- |
1288 ¬_cached); | |
1289 __ IncrementCounter(counters->string_ctor_cached_number(), 1); | |
1290 __ bind(&argument_is_string); | |
1291 // ----------- S t a t e ------------- | |
1292 // -- ebx : argument converted to string | |
1293 // -- edi : constructor function | |
1294 // -- esp[0] : return address | |
1295 // ----------------------------------- | |
1296 | 1304 |
1297 // Allocate a JSValue and put the tagged pointer into eax. | 1305 Label allocate, done_allocate; |
1298 Label gc_required; | 1306 __ Allocate(JSValue::kSize, eax, ecx, no_reg, &allocate, TAG_OBJECT); |
1299 __ Allocate(JSValue::kSize, | 1307 __ bind(&done_allocate); |
1300 eax, // Result. | |
1301 ecx, // New allocation top (we ignore it). | |
1302 no_reg, | |
1303 &gc_required, | |
1304 TAG_OBJECT); | |
1305 | 1308 |
1306 // Set the map. | 1309 // Initialize the JSValue in eax. |
1307 __ LoadGlobalFunctionInitialMap(edi, ecx); | 1310 __ LoadGlobalFunctionInitialMap(edi, ecx); |
1308 if (FLAG_debug_code) { | 1311 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); |
1309 __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset), | 1312 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
1310 JSValue::kSize >> kPointerSizeLog2); | 1313 masm->isolate()->factory()->empty_fixed_array()); |
1311 __ Assert(equal, kUnexpectedStringWrapperInstanceSize); | 1314 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
1312 __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0); | 1315 masm->isolate()->factory()->empty_fixed_array()); |
1313 __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper); | 1316 __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); |
| 1317 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
| 1318 __ Ret(); |
| 1319 |
| 1320 // Fallback to the runtime to allocate in new space. |
| 1321 __ bind(&allocate); |
| 1322 { |
| 1323 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1324 __ Push(ebx); |
| 1325 __ Push(edi); |
| 1326 __ Push(Smi::FromInt(JSValue::kSize)); |
| 1327 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 1328 __ Pop(edi); |
| 1329 __ Pop(ebx); |
| 1330 } |
| 1331 __ jmp(&done_allocate); |
1314 } | 1332 } |
1315 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); | |
1316 | |
1317 // Set properties and elements. | |
1318 Factory* factory = masm->isolate()->factory(); | |
1319 __ Move(ecx, Immediate(factory->empty_fixed_array())); | |
1320 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); | |
1321 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx); | |
1322 | |
1323 // Set the value. | |
1324 __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); | |
1325 | |
1326 // Ensure the object is fully initialized. | |
1327 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); | |
1328 | |
1329 // We're done. Return. | |
1330 __ ret(0); | |
1331 | |
1332 // The argument was not found in the number to string cache. Check | |
1333 // if it's a string already before calling the conversion builtin. | |
1334 Label convert_argument; | |
1335 __ bind(¬_cached); | |
1336 STATIC_ASSERT(kSmiTag == 0); | |
1337 __ JumpIfSmi(eax, &convert_argument); | |
1338 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); | |
1339 __ j(NegateCondition(is_string), &convert_argument); | |
1340 __ mov(ebx, eax); | |
1341 __ IncrementCounter(counters->string_ctor_string_value(), 1); | |
1342 __ jmp(&argument_is_string); | |
1343 | |
1344 // Invoke the conversion builtin and put the result into ebx. | |
1345 __ bind(&convert_argument); | |
1346 __ IncrementCounter(counters->string_ctor_conversions(), 1); | |
1347 { | |
1348 FrameScope scope(masm, StackFrame::INTERNAL); | |
1349 __ push(edi); // Preserve the function. | |
1350 ToStringStub stub(masm->isolate()); | |
1351 __ CallStub(&stub); | |
1352 __ pop(edi); | |
1353 } | |
1354 __ mov(ebx, eax); | |
1355 __ jmp(&argument_is_string); | |
1356 | |
1357 // Load the empty string into ebx, remove the receiver from the | |
1358 // stack, and jump back to the case where the argument is a string. | |
1359 __ bind(&no_arguments); | |
1360 __ Move(ebx, Immediate(factory->empty_string())); | |
1361 __ pop(ecx); | |
1362 __ lea(esp, Operand(esp, kPointerSize)); | |
1363 __ push(ecx); | |
1364 __ jmp(&argument_is_string); | |
1365 | |
1366 // At this point the argument is already a string. Call runtime to | |
1367 // create a string wrapper. | |
1368 __ bind(&gc_required); | |
1369 __ IncrementCounter(counters->string_ctor_gc_required(), 1); | |
1370 { | |
1371 FrameScope scope(masm, StackFrame::INTERNAL); | |
1372 __ push(ebx); | |
1373 __ CallRuntime(Runtime::kNewStringWrapper, 1); | |
1374 } | |
1375 __ ret(0); | |
1376 } | 1333 } |
1377 | 1334 |
1378 | 1335 |
1379 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, | 1336 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, |
1380 Label* stack_overflow) { | 1337 Label* stack_overflow) { |
1381 // ----------- S t a t e ------------- | 1338 // ----------- S t a t e ------------- |
1382 // -- eax : actual number of arguments | 1339 // -- eax : actual number of arguments |
1383 // -- ebx : expected number of arguments | 1340 // -- ebx : expected number of arguments |
1384 // -- edi : function (passed through to callee) | 1341 // -- edi : function (passed through to callee) |
1385 // ----------------------------------- | 1342 // ----------------------------------- |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1758 | 1715 |
1759 __ bind(&ok); | 1716 __ bind(&ok); |
1760 __ ret(0); | 1717 __ ret(0); |
1761 } | 1718 } |
1762 | 1719 |
1763 #undef __ | 1720 #undef __ |
1764 } // namespace internal | 1721 } // namespace internal |
1765 } // namespace v8 | 1722 } // namespace v8 |
1766 | 1723 |
1767 #endif // V8_TARGET_ARCH_IA32 | 1724 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |