| 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_X64 | 5 #if V8_TARGET_ARCH_X64 |
| 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 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1305 | 1305 |
| 1306 | 1306 |
| 1307 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | 1307 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
| 1308 // ----------- S t a t e ------------- | 1308 // ----------- S t a t e ------------- |
| 1309 // -- rax : number of arguments | 1309 // -- rax : number of arguments |
| 1310 // -- rdi : constructor function | 1310 // -- rdi : constructor function |
| 1311 // -- rsp[0] : return address | 1311 // -- rsp[0] : return address |
| 1312 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1312 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1313 // -- rsp[(argc + 1) * 8] : receiver | 1313 // -- rsp[(argc + 1) * 8] : receiver |
| 1314 // ----------------------------------- | 1314 // ----------------------------------- |
| 1315 Counters* counters = masm->isolate()->counters(); | |
| 1316 __ IncrementCounter(counters->string_ctor_calls(), 1); | |
| 1317 | 1315 |
| 1318 if (FLAG_debug_code) { | 1316 // 1. Load the first argument into rbx and get rid of the rest (including the |
| 1319 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, rcx); | 1317 // receiver). |
| 1320 __ cmpp(rdi, rcx); | 1318 { |
| 1321 __ Assert(equal, kUnexpectedStringFunction); | 1319 StackArgumentsAccessor args(rsp, rax); |
| 1320 Label no_arguments, done; |
| 1321 __ testp(rax, rax); |
| 1322 __ j(zero, &no_arguments, Label::kNear); |
| 1323 __ movp(rbx, args.GetArgumentOperand(1)); |
| 1324 __ jmp(&done, Label::kNear); |
| 1325 __ bind(&no_arguments); |
| 1326 __ LoadRoot(rbx, Heap::kempty_stringRootIndex); |
| 1327 __ bind(&done); |
| 1328 __ PopReturnAddressTo(rcx); |
| 1329 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); |
| 1330 __ PushReturnAddressFrom(rcx); |
| 1322 } | 1331 } |
| 1323 | 1332 |
| 1324 // Load the first argument into rax and get rid of the rest | 1333 // 2. Make sure rbx is a string. |
| 1325 // (including the receiver). | 1334 { |
| 1326 StackArgumentsAccessor args(rsp, rax); | 1335 Label convert, done_convert; |
| 1327 Label no_arguments; | 1336 __ JumpIfSmi(rbx, &convert, Label::kNear); |
| 1328 __ testp(rax, rax); | 1337 __ CmpObjectType(rbx, FIRST_NONSTRING_TYPE, rdx); |
| 1329 __ j(zero, &no_arguments); | 1338 __ j(below, &done_convert); |
| 1330 __ movp(rbx, args.GetArgumentOperand(1)); | 1339 __ bind(&convert); |
| 1331 __ PopReturnAddressTo(rcx); | 1340 { |
| 1332 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | 1341 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1333 __ PushReturnAddressFrom(rcx); | 1342 ToStringStub stub(masm->isolate()); |
| 1334 __ movp(rax, rbx); | 1343 __ Push(rdi); |
| 1344 __ Move(rax, rbx); |
| 1345 __ CallStub(&stub); |
| 1346 __ Move(rbx, rax); |
| 1347 __ Pop(rdi); |
| 1348 } |
| 1349 __ bind(&done_convert); |
| 1350 } |
| 1335 | 1351 |
| 1336 // Lookup the argument in the number to string cache. | 1352 // 3. Allocate a JSValue wrapper for the string. |
| 1337 Label not_cached, argument_is_string; | 1353 { |
| 1338 __ LookupNumberStringCache(rax, // Input. | 1354 // ----------- S t a t e ------------- |
| 1339 rbx, // Result. | 1355 // -- rbx : the first argument |
| 1340 rcx, // Scratch 1. | 1356 // -- rdi : constructor function |
| 1341 rdx, // Scratch 2. | 1357 // ----------------------------------- |
| 1342 ¬_cached); | |
| 1343 __ IncrementCounter(counters->string_ctor_cached_number(), 1); | |
| 1344 __ bind(&argument_is_string); | |
| 1345 | 1358 |
| 1346 // ----------- S t a t e ------------- | 1359 Label allocate, done_allocate; |
| 1347 // -- rbx : argument converted to string | 1360 __ Allocate(JSValue::kSize, rax, rcx, no_reg, &allocate, TAG_OBJECT); |
| 1348 // -- rdi : constructor function | 1361 __ bind(&done_allocate); |
| 1349 // -- rsp[0] : return address | |
| 1350 // ----------------------------------- | |
| 1351 | 1362 |
| 1352 // Allocate a JSValue and put the tagged pointer into rax. | 1363 // Initialize the JSValue in rax. |
| 1353 Label gc_required; | 1364 __ LoadGlobalFunctionInitialMap(rdi, rcx); |
| 1354 __ Allocate(JSValue::kSize, | 1365 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rcx); |
| 1355 rax, // Result. | 1366 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); |
| 1356 rcx, // New allocation top (we ignore it). | 1367 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rcx); |
| 1357 no_reg, | 1368 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rcx); |
| 1358 &gc_required, | 1369 __ movp(FieldOperand(rax, JSValue::kValueOffset), rbx); |
| 1359 TAG_OBJECT); | 1370 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
| 1371 __ Ret(); |
| 1360 | 1372 |
| 1361 // Set the map. | 1373 // Fallback to the runtime to allocate in new space. |
| 1362 __ LoadGlobalFunctionInitialMap(rdi, rcx); | 1374 __ bind(&allocate); |
| 1363 if (FLAG_debug_code) { | 1375 { |
| 1364 __ cmpb(FieldOperand(rcx, Map::kInstanceSizeOffset), | 1376 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1365 Immediate(JSValue::kSize >> kPointerSizeLog2)); | 1377 __ Push(rbx); |
| 1366 __ Assert(equal, kUnexpectedStringWrapperInstanceSize); | 1378 __ Push(rdi); |
| 1367 __ cmpb(FieldOperand(rcx, Map::kUnusedPropertyFieldsOffset), Immediate(0)); | 1379 __ Push(Smi::FromInt(JSValue::kSize)); |
| 1368 __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper); | 1380 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 1381 __ Pop(rdi); |
| 1382 __ Pop(rbx); |
| 1383 } |
| 1384 __ jmp(&done_allocate); |
| 1369 } | 1385 } |
| 1370 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rcx); | |
| 1371 | |
| 1372 // Set properties and elements. | |
| 1373 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | |
| 1374 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rcx); | |
| 1375 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rcx); | |
| 1376 | |
| 1377 // Set the value. | |
| 1378 __ movp(FieldOperand(rax, JSValue::kValueOffset), rbx); | |
| 1379 | |
| 1380 // Ensure the object is fully initialized. | |
| 1381 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); | |
| 1382 | |
| 1383 // We're done. Return. | |
| 1384 __ ret(0); | |
| 1385 | |
| 1386 // The argument was not found in the number to string cache. Check | |
| 1387 // if it's a string already before calling the conversion builtin. | |
| 1388 Label convert_argument; | |
| 1389 __ bind(¬_cached); | |
| 1390 STATIC_ASSERT(kSmiTag == 0); | |
| 1391 __ JumpIfSmi(rax, &convert_argument); | |
| 1392 Condition is_string = masm->IsObjectStringType(rax, rbx, rcx); | |
| 1393 __ j(NegateCondition(is_string), &convert_argument); | |
| 1394 __ movp(rbx, rax); | |
| 1395 __ IncrementCounter(counters->string_ctor_string_value(), 1); | |
| 1396 __ jmp(&argument_is_string); | |
| 1397 | |
| 1398 // Invoke the conversion builtin and put the result into rbx. | |
| 1399 __ bind(&convert_argument); | |
| 1400 __ IncrementCounter(counters->string_ctor_conversions(), 1); | |
| 1401 { | |
| 1402 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 1403 __ Push(rdi); // Preserve the function. | |
| 1404 ToStringStub stub(masm->isolate()); | |
| 1405 __ CallStub(&stub); | |
| 1406 __ Pop(rdi); | |
| 1407 } | |
| 1408 __ movp(rbx, rax); | |
| 1409 __ jmp(&argument_is_string); | |
| 1410 | |
| 1411 // Load the empty string into rbx, remove the receiver from the | |
| 1412 // stack, and jump back to the case where the argument is a string. | |
| 1413 __ bind(&no_arguments); | |
| 1414 __ LoadRoot(rbx, Heap::kempty_stringRootIndex); | |
| 1415 __ PopReturnAddressTo(rcx); | |
| 1416 __ leap(rsp, Operand(rsp, kPointerSize)); | |
| 1417 __ PushReturnAddressFrom(rcx); | |
| 1418 __ jmp(&argument_is_string); | |
| 1419 | |
| 1420 // At this point the argument is already a string. Call runtime to | |
| 1421 // create a string wrapper. | |
| 1422 __ bind(&gc_required); | |
| 1423 __ IncrementCounter(counters->string_ctor_gc_required(), 1); | |
| 1424 { | |
| 1425 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 1426 __ Push(rbx); | |
| 1427 __ CallRuntime(Runtime::kNewStringWrapper, 1); | |
| 1428 } | |
| 1429 __ ret(0); | |
| 1430 } | 1386 } |
| 1431 | 1387 |
| 1432 | 1388 |
| 1433 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, | 1389 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, |
| 1434 Label* stack_overflow) { | 1390 Label* stack_overflow) { |
| 1435 // ----------- S t a t e ------------- | 1391 // ----------- S t a t e ------------- |
| 1436 // -- rax : actual number of arguments | 1392 // -- rax : actual number of arguments |
| 1437 // -- rbx : expected number of arguments | 1393 // -- rbx : expected number of arguments |
| 1438 // -- rdi: function (passed through to callee) | 1394 // -- rdi: function (passed through to callee) |
| 1439 // ----------------------------------- | 1395 // ----------------------------------- |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1818 __ ret(0); | 1774 __ ret(0); |
| 1819 } | 1775 } |
| 1820 | 1776 |
| 1821 | 1777 |
| 1822 #undef __ | 1778 #undef __ |
| 1823 | 1779 |
| 1824 } // namespace internal | 1780 } // namespace internal |
| 1825 } // namespace v8 | 1781 } // namespace v8 |
| 1826 | 1782 |
| 1827 #endif // V8_TARGET_ARCH_X64 | 1783 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |