| 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 |