OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 ParameterCount expected(0); | 323 ParameterCount expected(0); |
324 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET, | 324 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET, |
325 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 325 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
326 } else { | 326 } else { |
327 ParameterCount actual(rax); | 327 ParameterCount actual(rax); |
328 __ InvokeFunction(rdi, actual, CALL_FUNCTION, | 328 __ InvokeFunction(rdi, actual, CALL_FUNCTION, |
329 NullCallWrapper(), CALL_AS_METHOD); | 329 NullCallWrapper(), CALL_AS_METHOD); |
330 } | 330 } |
331 | 331 |
332 // Store offset of return address for deoptimizer. | 332 // Store offset of return address for deoptimizer. |
333 // TODO(849): Once Generate_StringConstructCode doesn't reuse this | 333 if (!is_api_function && !count_constructions) { |
334 // generator, we can drop the third condition below! | |
335 if (!is_api_function && !count_constructions && | |
336 masm->isolate()->heap()->construct_stub_deopt_pc_offset() == 0) { | |
337 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 334 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
338 } | 335 } |
339 | 336 |
340 // Restore context from the frame. | 337 // Restore context from the frame. |
341 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 338 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
342 | 339 |
343 // If the result is an object (in the ECMA sense), we should get rid | 340 // If the result is an object (in the ECMA sense), we should get rid |
344 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 341 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
345 // on page 74. | 342 // on page 74. |
346 Label use_receiver, exit; | 343 Label use_receiver, exit; |
(...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1428 // Jump to the generic construct code in case the specialized code cannot | 1425 // Jump to the generic construct code in case the specialized code cannot |
1429 // handle the construction. | 1426 // handle the construction. |
1430 __ bind(&generic_constructor); | 1427 __ bind(&generic_constructor); |
1431 Handle<Code> generic_construct_stub = | 1428 Handle<Code> generic_construct_stub = |
1432 masm->isolate()->builtins()->JSConstructStubGeneric(); | 1429 masm->isolate()->builtins()->JSConstructStubGeneric(); |
1433 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 1430 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
1434 } | 1431 } |
1435 | 1432 |
1436 | 1433 |
1437 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | 1434 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
1438 // TODO(849): implement custom construct stub. | 1435 // ----------- S t a t e ------------- |
1439 // Generate a copy of the generic stub for now. | 1436 // -- rax : number of arguments |
1440 Generate_JSConstructStubGeneric(masm); | 1437 // -- rdi : constructor function |
| 1438 // -- rsp[0] : return address |
| 1439 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1440 // -- rsp[(argc + 1) * 8] : receiver |
| 1441 // ----------------------------------- |
| 1442 Counters* counters = masm->isolate()->counters(); |
| 1443 __ IncrementCounter(counters->string_ctor_calls(), 1); |
| 1444 |
| 1445 if (FLAG_debug_code) { |
| 1446 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, rcx); |
| 1447 __ cmpq(rdi, rcx); |
| 1448 __ Assert(equal, "Unexpected String function"); |
| 1449 } |
| 1450 |
| 1451 // Load the first argument into rax and get rid of the rest |
| 1452 // (including the receiver). |
| 1453 Label no_arguments; |
| 1454 __ testq(rax, rax); |
| 1455 __ j(zero, &no_arguments); |
| 1456 __ movq(rbx, Operand(rsp, rax, times_pointer_size, 0)); |
| 1457 __ pop(rcx); |
| 1458 __ lea(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); |
| 1459 __ push(rcx); |
| 1460 __ movq(rax, rbx); |
| 1461 |
| 1462 // Lookup the argument in the number to string cache. |
| 1463 Label not_cached, argument_is_string; |
| 1464 NumberToStringStub::GenerateLookupNumberStringCache( |
| 1465 masm, |
| 1466 rax, // Input. |
| 1467 rbx, // Result. |
| 1468 rcx, // Scratch 1. |
| 1469 rdx, // Scratch 2. |
| 1470 false, // Input is known to be smi? |
| 1471 ¬_cached); |
| 1472 __ IncrementCounter(counters->string_ctor_cached_number(), 1); |
| 1473 __ bind(&argument_is_string); |
| 1474 |
| 1475 // ----------- S t a t e ------------- |
| 1476 // -- rbx : argument converted to string |
| 1477 // -- rdi : constructor function |
| 1478 // -- rsp[0] : return address |
| 1479 // ----------------------------------- |
| 1480 |
| 1481 // Allocate a JSValue and put the tagged pointer into rax. |
| 1482 Label gc_required; |
| 1483 __ AllocateInNewSpace(JSValue::kSize, |
| 1484 rax, // Result. |
| 1485 rcx, // New allocation top (we ignore it). |
| 1486 no_reg, |
| 1487 &gc_required, |
| 1488 TAG_OBJECT); |
| 1489 |
| 1490 // Set the map. |
| 1491 __ LoadGlobalFunctionInitialMap(rdi, rcx); |
| 1492 if (FLAG_debug_code) { |
| 1493 __ cmpb(FieldOperand(rcx, Map::kInstanceSizeOffset), |
| 1494 Immediate(JSValue::kSize >> kPointerSizeLog2)); |
| 1495 __ Assert(equal, "Unexpected string wrapper instance size"); |
| 1496 __ cmpb(FieldOperand(rcx, Map::kUnusedPropertyFieldsOffset), Immediate(0)); |
| 1497 __ Assert(equal, "Unexpected unused properties of string wrapper"); |
| 1498 } |
| 1499 __ movq(FieldOperand(rax, HeapObject::kMapOffset), rcx); |
| 1500 |
| 1501 // Set properties and elements. |
| 1502 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); |
| 1503 __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), rcx); |
| 1504 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rcx); |
| 1505 |
| 1506 // Set the value. |
| 1507 __ movq(FieldOperand(rax, JSValue::kValueOffset), rbx); |
| 1508 |
| 1509 // Ensure the object is fully initialized. |
| 1510 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
| 1511 |
| 1512 // We're done. Return. |
| 1513 __ ret(0); |
| 1514 |
| 1515 // The argument was not found in the number to string cache. Check |
| 1516 // if it's a string already before calling the conversion builtin. |
| 1517 Label convert_argument; |
| 1518 __ bind(¬_cached); |
| 1519 STATIC_ASSERT(kSmiTag == 0); |
| 1520 __ JumpIfSmi(rax, &convert_argument); |
| 1521 Condition is_string = masm->IsObjectStringType(rax, rbx, rcx); |
| 1522 __ j(NegateCondition(is_string), &convert_argument); |
| 1523 __ movq(rbx, rax); |
| 1524 __ IncrementCounter(counters->string_ctor_string_value(), 1); |
| 1525 __ jmp(&argument_is_string); |
| 1526 |
| 1527 // Invoke the conversion builtin and put the result into rbx. |
| 1528 __ bind(&convert_argument); |
| 1529 __ IncrementCounter(counters->string_ctor_conversions(), 1); |
| 1530 { |
| 1531 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1532 __ push(rdi); // Preserve the function. |
| 1533 __ push(rax); |
| 1534 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); |
| 1535 __ pop(rdi); |
| 1536 } |
| 1537 __ movq(rbx, rax); |
| 1538 __ jmp(&argument_is_string); |
| 1539 |
| 1540 // Load the empty string into rbx, remove the receiver from the |
| 1541 // stack, and jump back to the case where the argument is a string. |
| 1542 __ bind(&no_arguments); |
| 1543 __ LoadRoot(rbx, Heap::kEmptyStringRootIndex); |
| 1544 __ pop(rcx); |
| 1545 __ lea(rsp, Operand(rsp, kPointerSize)); |
| 1546 __ push(rcx); |
| 1547 __ jmp(&argument_is_string); |
| 1548 |
| 1549 // At this point the argument is already a string. Call runtime to |
| 1550 // create a string wrapper. |
| 1551 __ bind(&gc_required); |
| 1552 __ IncrementCounter(counters->string_ctor_gc_required(), 1); |
| 1553 { |
| 1554 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1555 __ push(rbx); |
| 1556 __ CallRuntime(Runtime::kNewStringWrapper, 1); |
| 1557 } |
| 1558 __ ret(0); |
1441 } | 1559 } |
1442 | 1560 |
1443 | 1561 |
1444 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { | 1562 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
1445 __ push(rbp); | 1563 __ push(rbp); |
1446 __ movq(rbp, rsp); | 1564 __ movq(rbp, rsp); |
1447 | 1565 |
1448 // Store the arguments adaptor context sentinel. | 1566 // Store the arguments adaptor context sentinel. |
1449 __ Push(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1567 __ Push(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
1450 | 1568 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1618 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 1736 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
1619 generator.Generate(); | 1737 generator.Generate(); |
1620 } | 1738 } |
1621 | 1739 |
1622 | 1740 |
1623 #undef __ | 1741 #undef __ |
1624 | 1742 |
1625 } } // namespace v8::internal | 1743 } } // namespace v8::internal |
1626 | 1744 |
1627 #endif // V8_TARGET_ARCH_X64 | 1745 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |