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 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 329 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
330 GenerateTailCallToReturnedCode(masm); | 330 GenerateTailCallToReturnedCode(masm); |
331 | 331 |
332 __ bind(&ok); | 332 __ bind(&ok); |
333 GenerateTailCallToSharedCode(masm); | 333 GenerateTailCallToSharedCode(masm); |
334 } | 334 } |
335 | 335 |
336 | 336 |
337 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 337 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
338 bool is_api_function, | 338 bool is_api_function, |
339 bool count_constructions) { | 339 bool count_constructions, |
| 340 bool create_memento) { |
340 // ----------- S t a t e ------------- | 341 // ----------- S t a t e ------------- |
341 // -- r0 : number of arguments | 342 // -- r0 : number of arguments |
342 // -- r1 : constructor function | 343 // -- r1 : constructor function |
| 344 // -- r2 : allocation site or undefined |
343 // -- lr : return address | 345 // -- lr : return address |
344 // -- sp[...]: constructor arguments | 346 // -- sp[...]: constructor arguments |
345 // ----------------------------------- | 347 // ----------------------------------- |
346 | 348 |
347 // Should never count constructions for api objects. | 349 // Should never count constructions for api objects. |
348 ASSERT(!is_api_function || !count_constructions); | 350 ASSERT(!is_api_function || !count_constructions); |
349 | 351 |
| 352 // Should never create mementos for api functions. |
| 353 ASSERT(!is_api_function || !create_memento); |
| 354 |
| 355 // Should never create mementos before slack tracking is finished. |
| 356 ASSERT(!count_constructions || !create_memento); |
| 357 |
350 Isolate* isolate = masm->isolate(); | 358 Isolate* isolate = masm->isolate(); |
351 | 359 |
352 // Enter a construct frame. | 360 // Enter a construct frame. |
353 { | 361 { |
354 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | 362 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); |
355 | 363 |
| 364 if (create_memento) { |
| 365 __ AssertUndefinedOrAllocationSite(r2, r3); |
| 366 __ push(r2); |
| 367 } |
| 368 |
356 // Preserve the two incoming parameters on the stack. | 369 // Preserve the two incoming parameters on the stack. |
357 __ SmiTag(r0); | 370 __ SmiTag(r0); |
358 __ push(r0); // Smi-tagged arguments count. | 371 __ push(r0); // Smi-tagged arguments count. |
359 __ push(r1); // Constructor function. | 372 __ push(r1); // Constructor function. |
360 | 373 |
361 // Try to allocate the object without transitioning into C code. If any of | 374 // Try to allocate the object without transitioning into C code. If any of |
362 // the preconditions is not met, the code bails out to the runtime call. | 375 // the preconditions is not met, the code bails out to the runtime call. |
363 Label rt_call, allocated; | 376 Label rt_call, allocated; |
364 if (FLAG_inline_new) { | 377 if (FLAG_inline_new) { |
365 Label undo_allocation; | 378 Label undo_allocation; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 __ pop(r2); | 420 __ pop(r2); |
408 __ pop(r1); | 421 __ pop(r1); |
409 | 422 |
410 __ bind(&allocate); | 423 __ bind(&allocate); |
411 } | 424 } |
412 | 425 |
413 // Now allocate the JSObject on the heap. | 426 // Now allocate the JSObject on the heap. |
414 // r1: constructor function | 427 // r1: constructor function |
415 // r2: initial map | 428 // r2: initial map |
416 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); | 429 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); |
| 430 if (create_memento) { |
| 431 __ add(r3, r3, Operand(AllocationMemento::kSize / kPointerSize)); |
| 432 } |
| 433 |
417 __ Allocate(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); | 434 __ Allocate(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); |
418 | 435 |
419 // Allocated the JSObject, now initialize the fields. Map is set to | 436 // Allocated the JSObject, now initialize the fields. Map is set to |
420 // initial map and properties and elements are set to empty fixed array. | 437 // initial map and properties and elements are set to empty fixed array. |
421 // r1: constructor function | 438 // r1: constructor function |
422 // r2: initial map | 439 // r2: initial map |
423 // r3: object size | 440 // r3: object size (not including memento if create_memento) |
424 // r4: JSObject (not tagged) | 441 // r4: JSObject (not tagged) |
425 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); | 442 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); |
426 __ mov(r5, r4); | 443 __ mov(r5, r4); |
427 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); | 444 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); |
428 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); | 445 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); |
429 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); | 446 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); |
430 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); | 447 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
431 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); | 448 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); |
432 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); | 449 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
433 | 450 |
434 // Fill all the in-object properties with the appropriate filler. | 451 // Fill all the in-object properties with the appropriate filler. |
435 // r1: constructor function | 452 // r1: constructor function |
436 // r2: initial map | 453 // r2: initial map |
437 // r3: object size (in words) | 454 // r3: object size (in words, including memento if create_memento) |
438 // r4: JSObject (not tagged) | 455 // r4: JSObject (not tagged) |
439 // r5: First in-object property of JSObject (not tagged) | 456 // r5: First in-object property of JSObject (not tagged) |
440 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); | 457 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); |
441 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); | 458 |
442 if (count_constructions) { | 459 if (count_constructions) { |
| 460 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); |
443 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); | 461 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); |
444 __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, | 462 __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, |
445 kBitsPerByte); | 463 kBitsPerByte); |
446 __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2)); | 464 __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2)); |
447 // r0: offset of first field after pre-allocated fields | 465 // r0: offset of first field after pre-allocated fields |
448 if (FLAG_debug_code) { | 466 if (FLAG_debug_code) { |
449 __ add(ip, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. | 467 __ add(ip, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. |
450 __ cmp(r0, ip); | 468 __ cmp(r0, ip); |
451 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); | 469 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); |
452 } | 470 } |
453 __ InitializeFieldsWithFiller(r5, r0, r6); | 471 __ InitializeFieldsWithFiller(r5, r0, r6); |
454 // To allow for truncation. | 472 // To allow for truncation. |
455 __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex); | 473 __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex); |
| 474 __ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. |
| 475 __ InitializeFieldsWithFiller(r5, r0, r6); |
| 476 } else if (create_memento) { |
| 477 __ sub(r6, r3, Operand(AllocationMemento::kSize / kPointerSize)); |
| 478 __ add(r0, r4, Operand(r6, LSL, kPointerSizeLog2)); // End of object. |
| 479 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); |
| 480 __ InitializeFieldsWithFiller(r5, r0, r6); |
| 481 |
| 482 // Fill in memento fields. |
| 483 // r5: points to the allocated but uninitialized memento. |
| 484 __ LoadRoot(r6, Heap::kAllocationMementoMapRootIndex); |
| 485 ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset); |
| 486 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
| 487 // Load the AllocationSite |
| 488 __ ldr(r6, MemOperand(sp, 2 * kPointerSize)); |
| 489 ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); |
| 490 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
| 491 } else { |
| 492 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); |
| 493 __ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. |
| 494 __ InitializeFieldsWithFiller(r5, r0, r6); |
456 } | 495 } |
457 __ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. | |
458 __ InitializeFieldsWithFiller(r5, r0, r6); | |
459 | 496 |
460 // Add the object tag to make the JSObject real, so that we can continue | 497 // Add the object tag to make the JSObject real, so that we can continue |
461 // and jump into the continuation code at any time from now on. Any | 498 // and jump into the continuation code at any time from now on. Any |
462 // failures need to undo the allocation, so that the heap is in a | 499 // failures need to undo the allocation, so that the heap is in a |
463 // consistent state and verifiable. | 500 // consistent state and verifiable. |
464 __ add(r4, r4, Operand(kHeapObjectTag)); | 501 __ add(r4, r4, Operand(kHeapObjectTag)); |
465 | 502 |
466 // Check if a non-empty properties array is needed. Continue with | 503 // Check if a non-empty properties array is needed. Continue with |
467 // allocated object if not fall through to runtime call if it is. | 504 // allocated object if not fall through to runtime call if it is. |
468 // r1: constructor function | 505 // r1: constructor function |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 // example, the map's unused properties potentially do not match the | 583 // example, the map's unused properties potentially do not match the |
547 // allocated objects unused properties. | 584 // allocated objects unused properties. |
548 // r4: JSObject (previous new top) | 585 // r4: JSObject (previous new top) |
549 __ bind(&undo_allocation); | 586 __ bind(&undo_allocation); |
550 __ UndoAllocationInNewSpace(r4, r5); | 587 __ UndoAllocationInNewSpace(r4, r5); |
551 } | 588 } |
552 | 589 |
553 // Allocate the new receiver object using the runtime call. | 590 // Allocate the new receiver object using the runtime call. |
554 // r1: constructor function | 591 // r1: constructor function |
555 __ bind(&rt_call); | 592 __ bind(&rt_call); |
| 593 if (create_memento) { |
| 594 // Get the cell or allocation site. |
| 595 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); |
| 596 __ push(r2); |
| 597 } |
| 598 |
556 __ push(r1); // argument for Runtime_NewObject | 599 __ push(r1); // argument for Runtime_NewObject |
557 __ CallRuntime(Runtime::kNewObject, 1); | 600 if (create_memento) { |
| 601 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 2); |
| 602 } else { |
| 603 __ CallRuntime(Runtime::kNewObject, 1); |
| 604 } |
558 __ mov(r4, r0); | 605 __ mov(r4, r0); |
559 | 606 |
| 607 // If we ended up using the runtime, and we want a memento, then the |
| 608 // runtime call made it for us, and we shouldn't do create count |
| 609 // increment. |
| 610 Label count_incremented; |
| 611 if (create_memento) { |
| 612 __ jmp(&count_incremented); |
| 613 } |
| 614 |
560 // Receiver for constructor call allocated. | 615 // Receiver for constructor call allocated. |
561 // r4: JSObject | 616 // r4: JSObject |
562 __ bind(&allocated); | 617 __ bind(&allocated); |
| 618 |
| 619 if (create_memento) { |
| 620 __ ldr(r2, MemOperand(sp, kPointerSize * 2)); |
| 621 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
| 622 __ cmp(r2, r5); |
| 623 __ b(eq, &count_incremented); |
| 624 // r2 is an AllocationSite. We are creating a memento from it, so we |
| 625 // need to increment the memento create count. |
| 626 __ ldr(r3, FieldMemOperand(r2, |
| 627 AllocationSite::kPretenureCreateCountOffset)); |
| 628 __ add(r3, r3, Operand(Smi::FromInt(1))); |
| 629 __ str(r3, FieldMemOperand(r2, |
| 630 AllocationSite::kPretenureCreateCountOffset)); |
| 631 __ bind(&count_incremented); |
| 632 } |
| 633 |
563 __ push(r4); | 634 __ push(r4); |
564 __ push(r4); | 635 __ push(r4); |
565 | 636 |
566 // Reload the number of arguments and the constructor from the stack. | 637 // Reload the number of arguments and the constructor from the stack. |
567 // sp[0]: receiver | 638 // sp[0]: receiver |
568 // sp[1]: receiver | 639 // sp[1]: receiver |
569 // sp[2]: constructor function | 640 // sp[2]: constructor function |
570 // sp[3]: number of arguments (smi-tagged) | 641 // sp[3]: number of arguments (smi-tagged) |
571 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); | 642 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); |
572 __ ldr(r3, MemOperand(sp, 3 * kPointerSize)); | 643 __ ldr(r3, MemOperand(sp, 3 * kPointerSize)); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 } | 726 } |
656 | 727 |
657 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); | 728 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); |
658 __ add(sp, sp, Operand(kPointerSize)); | 729 __ add(sp, sp, Operand(kPointerSize)); |
659 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); | 730 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); |
660 __ Jump(lr); | 731 __ Jump(lr); |
661 } | 732 } |
662 | 733 |
663 | 734 |
664 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { | 735 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { |
665 Generate_JSConstructStubHelper(masm, false, true); | 736 Generate_JSConstructStubHelper(masm, false, true, false); |
666 } | 737 } |
667 | 738 |
668 | 739 |
669 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 740 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
670 Generate_JSConstructStubHelper(masm, false, false); | 741 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
671 } | 742 } |
672 | 743 |
673 | 744 |
674 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 745 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
675 Generate_JSConstructStubHelper(masm, true, false); | 746 Generate_JSConstructStubHelper(masm, true, false, false); |
676 } | 747 } |
677 | 748 |
678 | 749 |
679 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 750 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
680 bool is_construct) { | 751 bool is_construct) { |
681 // Called from Generate_JS_Entry | 752 // Called from Generate_JS_Entry |
682 // r0: code entry | 753 // r0: code entry |
683 // r1: function | 754 // r1: function |
684 // r2: receiver | 755 // r2: receiver |
685 // r3: argc | 756 // r3: argc |
(...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1475 __ bind(&dont_adapt_arguments); | 1546 __ bind(&dont_adapt_arguments); |
1476 __ Jump(r3); | 1547 __ Jump(r3); |
1477 } | 1548 } |
1478 | 1549 |
1479 | 1550 |
1480 #undef __ | 1551 #undef __ |
1481 | 1552 |
1482 } } // namespace v8::internal | 1553 } } // namespace v8::internal |
1483 | 1554 |
1484 #endif // V8_TARGET_ARCH_ARM | 1555 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |