| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 320 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
| 321 GenerateTailCallToReturnedCode(masm); | 321 GenerateTailCallToReturnedCode(masm); |
| 322 | 322 |
| 323 __ Bind(&ok); | 323 __ Bind(&ok); |
| 324 GenerateTailCallToSharedCode(masm); | 324 GenerateTailCallToSharedCode(masm); |
| 325 } | 325 } |
| 326 | 326 |
| 327 | 327 |
| 328 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 328 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
| 329 bool is_api_function, | 329 bool is_api_function, |
| 330 bool count_constructions) { | 330 bool count_constructions, |
| 331 bool create_memento) { |
| 331 // ----------- S t a t e ------------- | 332 // ----------- S t a t e ------------- |
| 332 // -- x0 : number of arguments | 333 // -- x0 : number of arguments |
| 333 // -- x1 : constructor function | 334 // -- x1 : constructor function |
| 335 // -- x2 : allocation site or undefined |
| 334 // -- lr : return address | 336 // -- lr : return address |
| 335 // -- sp[...]: constructor arguments | 337 // -- sp[...]: constructor arguments |
| 336 // ----------------------------------- | 338 // ----------------------------------- |
| 337 | 339 |
| 338 ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); | 340 ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); |
| 339 // Should never count constructions for api objects. | 341 // Should never count constructions for api objects. |
| 340 ASSERT(!is_api_function || !count_constructions); | 342 ASSERT(!is_api_function || !count_constructions); |
| 343 // Should never create mementos for api functions. |
| 344 ASSERT(!is_api_function || !create_memento); |
| 345 // Should never create mementos before slack tracking is finished. |
| 346 ASSERT(!count_constructions || !create_memento); |
| 341 | 347 |
| 342 Isolate* isolate = masm->isolate(); | 348 Isolate* isolate = masm->isolate(); |
| 343 | 349 |
| 344 // Enter a construct frame. | 350 // Enter a construct frame. |
| 345 { | 351 { |
| 346 FrameScope scope(masm, StackFrame::CONSTRUCT); | 352 FrameScope scope(masm, StackFrame::CONSTRUCT); |
| 347 | 353 |
| 348 // Preserve the two incoming parameters on the stack. | 354 // Preserve the three incoming parameters on the stack. |
| 355 if (create_memento) { |
| 356 __ AssertUndefinedOrAllocationSite(x2, x10); |
| 357 __ Push(x2); |
| 358 } |
| 359 |
| 349 Register argc = x0; | 360 Register argc = x0; |
| 350 Register constructor = x1; | 361 Register constructor = x1; |
| 351 // x1: constructor function | 362 // x1: constructor function |
| 352 __ SmiTag(argc); | 363 __ SmiTag(argc); |
| 353 __ Push(argc, constructor); | 364 __ Push(argc, constructor); |
| 354 // sp[0] : Constructor function. | 365 // sp[0] : Constructor function. |
| 355 // sp[1]: number of arguments (smi-tagged) | 366 // sp[1]: number of arguments (smi-tagged) |
| 356 | 367 |
| 357 // Try to allocate the object without transitioning into C code. If any of | 368 // Try to allocate the object without transitioning into C code. If any of |
| 358 // the preconditions is not met, the code bails out to the runtime call. | 369 // the preconditions is not met, the code bails out to the runtime call. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 // The call will replace the stub, so the countdown is only done once. | 409 // The call will replace the stub, so the countdown is only done once. |
| 399 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | 410 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
| 400 __ Pop(init_map, constructor); | 411 __ Pop(init_map, constructor); |
| 401 __ Bind(&allocate); | 412 __ Bind(&allocate); |
| 402 } | 413 } |
| 403 | 414 |
| 404 // Now allocate the JSObject on the heap. | 415 // Now allocate the JSObject on the heap. |
| 405 Register obj_size = x3; | 416 Register obj_size = x3; |
| 406 Register new_obj = x4; | 417 Register new_obj = x4; |
| 407 __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset)); | 418 __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset)); |
| 408 __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); | 419 if (create_memento) { |
| 420 __ Add(x7, obj_size, |
| 421 Operand(AllocationMemento::kSize / kPointerSize)); |
| 422 __ Allocate(x7, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); |
| 423 } else { |
| 424 __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); |
| 425 } |
| 409 | 426 |
| 410 // Allocated the JSObject, now initialize the fields. Map is set to | 427 // Allocated the JSObject, now initialize the fields. Map is set to |
| 411 // initial map and properties and elements are set to empty fixed array. | 428 // initial map and properties and elements are set to empty fixed array. |
| 412 // NB. the object pointer is not tagged, so MemOperand is used. | 429 // NB. the object pointer is not tagged, so MemOperand is used. |
| 413 Register empty = x5; | 430 Register empty = x5; |
| 414 __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); | 431 __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); |
| 415 __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset)); | 432 __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset)); |
| 416 STATIC_ASSERT(JSObject::kElementsOffset == | 433 STATIC_ASSERT(JSObject::kElementsOffset == |
| 417 (JSObject::kPropertiesOffset + kPointerSize)); | 434 (JSObject::kPropertiesOffset + kPointerSize)); |
| 418 __ Stp(empty, empty, MemOperand(new_obj, JSObject::kPropertiesOffset)); | 435 __ Stp(empty, empty, MemOperand(new_obj, JSObject::kPropertiesOffset)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 } | 477 } |
| 461 | 478 |
| 462 // Fill the remaining fields with one pointer filler map. | 479 // Fill the remaining fields with one pointer filler map. |
| 463 Register one_pointer_filler = x5; | 480 Register one_pointer_filler = x5; |
| 464 Register non_prealloc_fields = x6; | 481 Register non_prealloc_fields = x6; |
| 465 __ LoadRoot(one_pointer_filler, Heap::kOnePointerFillerMapRootIndex); | 482 __ LoadRoot(one_pointer_filler, Heap::kOnePointerFillerMapRootIndex); |
| 466 __ Sub(non_prealloc_fields, prop_fields, prealloc_fields); | 483 __ Sub(non_prealloc_fields, prop_fields, prealloc_fields); |
| 467 __ FillFields(first_non_prealloc, non_prealloc_fields, | 484 __ FillFields(first_non_prealloc, non_prealloc_fields, |
| 468 one_pointer_filler); | 485 one_pointer_filler); |
| 469 prop_fields = NoReg; | 486 prop_fields = NoReg; |
| 487 } else if (create_memento) { |
| 488 // Fill the pre-allocated fields with undef. |
| 489 __ FillFields(first_prop, prop_fields, undef); |
| 490 __ Add(first_prop, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); |
| 491 __ LoadRoot(x14, Heap::kAllocationMementoMapRootIndex); |
| 492 ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset); |
| 493 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); |
| 494 // Load the AllocationSite |
| 495 __ Peek(x14, 2 * kXRegSize); |
| 496 ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); |
| 497 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); |
| 498 first_prop = NoReg; |
| 470 } else { | 499 } else { |
| 471 // Fill all of the property fields with undef. | 500 // Fill all of the property fields with undef. |
| 472 __ FillFields(first_prop, prop_fields, undef); | 501 __ FillFields(first_prop, prop_fields, undef); |
| 473 first_prop = NoReg; | 502 first_prop = NoReg; |
| 474 prop_fields = NoReg; | 503 prop_fields = NoReg; |
| 475 } | 504 } |
| 476 | 505 |
| 477 // Add the object tag to make the JSObject real, so that we can continue | 506 // Add the object tag to make the JSObject real, so that we can continue |
| 478 // and jump into the continuation code at any time from now on. Any | 507 // and jump into the continuation code at any time from now on. Any |
| 479 // failures need to undo the allocation, so that the heap is in a | 508 // failures need to undo the allocation, so that the heap is in a |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 | 553 |
| 525 // Undo the setting of the new top so that the heap is verifiable. For | 554 // Undo the setting of the new top so that the heap is verifiable. For |
| 526 // example, the map's unused properties potentially do not match the | 555 // example, the map's unused properties potentially do not match the |
| 527 // allocated objects unused properties. | 556 // allocated objects unused properties. |
| 528 __ Bind(&undo_allocation); | 557 __ Bind(&undo_allocation); |
| 529 __ UndoAllocationInNewSpace(new_obj, x14); | 558 __ UndoAllocationInNewSpace(new_obj, x14); |
| 530 } | 559 } |
| 531 | 560 |
| 532 // Allocate the new receiver object using the runtime call. | 561 // Allocate the new receiver object using the runtime call. |
| 533 __ Bind(&rt_call); | 562 __ Bind(&rt_call); |
| 534 __ Push(constructor); // Argument for Runtime_NewObject. | 563 Label count_incremented; |
| 535 __ CallRuntime(Runtime::kNewObject, 1); | 564 if (create_memento) { |
| 536 __ Mov(x4, x0); | 565 // Get the cell or allocation site. |
| 566 __ Peek(x4, 2 * kXRegSize); |
| 567 __ Push(x4); |
| 568 __ Push(constructor); // Argument for Runtime_NewObject. |
| 569 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 2); |
| 570 __ Mov(x4, x0); |
| 571 // If we ended up using the runtime, and we want a memento, then the |
| 572 // runtime call made it for us, and we shouldn't do create count |
| 573 // increment. |
| 574 __ jmp(&count_incremented); |
| 575 } else { |
| 576 __ Push(constructor); // Argument for Runtime_NewObject. |
| 577 __ CallRuntime(Runtime::kNewObject, 1); |
| 578 __ Mov(x4, x0); |
| 579 } |
| 537 | 580 |
| 538 // Receiver for constructor call allocated. | 581 // Receiver for constructor call allocated. |
| 539 // x4: JSObject | 582 // x4: JSObject |
| 540 __ Bind(&allocated); | 583 __ Bind(&allocated); |
| 584 |
| 585 if (create_memento) { |
| 586 __ Peek(x10, 2 * kXRegSize); |
| 587 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); |
| 588 // r2 is an AllocationSite. We are creating a memento from it, so we |
| 589 // need to increment the memento create count. |
| 590 __ Ldr(x5, FieldMemOperand(x10, |
| 591 AllocationSite::kPretenureCreateCountOffset)); |
| 592 __ Add(x5, x5, Operand(Smi::FromInt(1))); |
| 593 __ Str(x5, FieldMemOperand(x10, |
| 594 AllocationSite::kPretenureCreateCountOffset)); |
| 595 __ bind(&count_incremented); |
| 596 } |
| 597 |
| 541 __ Push(x4, x4); | 598 __ Push(x4, x4); |
| 542 | 599 |
| 543 // Reload the number of arguments from the stack. | 600 // Reload the number of arguments from the stack. |
| 544 // Set it up in x0 for the function call below. | 601 // Set it up in x0 for the function call below. |
| 545 // jssp[0]: receiver | 602 // jssp[0]: receiver |
| 546 // jssp[1]: receiver | 603 // jssp[1]: receiver |
| 547 // jssp[2]: constructor function | 604 // jssp[2]: constructor function |
| 548 // jssp[3]: number of arguments (smi-tagged) | 605 // jssp[3]: number of arguments (smi-tagged) |
| 549 __ Peek(constructor, 2 * kXRegSize); // Load constructor. | 606 __ Peek(constructor, 2 * kXRegSize); // Load constructor. |
| 550 __ Peek(argc, 3 * kXRegSize); // Load number of arguments. | 607 __ Peek(argc, 3 * kXRegSize); // Load number of arguments. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 } | 694 } |
| 638 | 695 |
| 639 __ DropBySMI(x1); | 696 __ DropBySMI(x1); |
| 640 __ Drop(1); | 697 __ Drop(1); |
| 641 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); | 698 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); |
| 642 __ Ret(); | 699 __ Ret(); |
| 643 } | 700 } |
| 644 | 701 |
| 645 | 702 |
| 646 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { | 703 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { |
| 647 Generate_JSConstructStubHelper(masm, false, true); | 704 Generate_JSConstructStubHelper(masm, false, true, false); |
| 648 } | 705 } |
| 649 | 706 |
| 650 | 707 |
| 651 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 708 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
| 652 Generate_JSConstructStubHelper(masm, false, false); | 709 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
| 653 } | 710 } |
| 654 | 711 |
| 655 | 712 |
| 656 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 713 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
| 657 Generate_JSConstructStubHelper(masm, true, false); | 714 Generate_JSConstructStubHelper(masm, true, false, false); |
| 658 } | 715 } |
| 659 | 716 |
| 660 | 717 |
| 661 // Input: | 718 // Input: |
| 662 // x0: code entry. | 719 // x0: code entry. |
| 663 // x1: function. | 720 // x1: function. |
| 664 // x2: receiver. | 721 // x2: receiver. |
| 665 // x3: argc. | 722 // x3: argc. |
| 666 // x4: argv. | 723 // x4: argv. |
| 667 // Output: | 724 // Output: |
| (...skipping 828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1496 __ Bind(&dont_adapt_arguments); | 1553 __ Bind(&dont_adapt_arguments); |
| 1497 __ Jump(code_entry); | 1554 __ Jump(code_entry); |
| 1498 } | 1555 } |
| 1499 | 1556 |
| 1500 | 1557 |
| 1501 #undef __ | 1558 #undef __ |
| 1502 | 1559 |
| 1503 } } // namespace v8::internal | 1560 } } // namespace v8::internal |
| 1504 | 1561 |
| 1505 #endif // V8_TARGET_ARCH_ARM | 1562 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |