OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_PPC | 7 #if V8_TARGET_ARCH_PPC |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 __ bge(&ok); | 299 __ bge(&ok); |
300 | 300 |
301 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 301 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
302 GenerateTailCallToReturnedCode(masm); | 302 GenerateTailCallToReturnedCode(masm); |
303 | 303 |
304 __ bind(&ok); | 304 __ bind(&ok); |
305 GenerateTailCallToSharedCode(masm); | 305 GenerateTailCallToSharedCode(masm); |
306 } | 306 } |
307 | 307 |
308 | 308 |
| 309 static void Generate_Runtime_NewObject(MacroAssembler* masm, |
| 310 bool create_memento, |
| 311 Register original_constructor, |
| 312 Label* count_incremented, |
| 313 Label* allocated) { |
| 314 // ----------- S t a t e ------------- |
| 315 // -- r4: argument for Runtime_NewObject |
| 316 // ----------------------------------- |
| 317 Register result = r7; |
| 318 |
| 319 if (create_memento) { |
| 320 // Get the cell or allocation site. |
| 321 __ LoadP(r5, MemOperand(sp, 2 * kPointerSize)); |
| 322 __ Push(r5, r4, original_constructor); |
| 323 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); |
| 324 __ mr(result, r3); |
| 325 // Runtime_NewObjectWithAllocationSite increments allocation count. |
| 326 // Skip the increment. |
| 327 __ b(count_incremented); |
| 328 } else { |
| 329 __ Push(r4, original_constructor); |
| 330 __ CallRuntime(Runtime::kNewObject, 2); |
| 331 __ mr(result, r3); |
| 332 __ b(allocated); |
| 333 } |
| 334 } |
| 335 |
| 336 |
309 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 337 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
310 bool is_api_function, | 338 bool is_api_function, |
311 bool create_memento) { | 339 bool create_memento) { |
312 // ----------- S t a t e ------------- | 340 // ----------- S t a t e ------------- |
313 // -- r3 : number of arguments | 341 // -- r3 : number of arguments |
314 // -- r4 : constructor function | 342 // -- r4 : constructor function |
315 // -- r5 : allocation site or undefined | 343 // -- r5 : allocation site or undefined |
| 344 // -- r6 : original constructor |
316 // -- lr : return address | 345 // -- lr : return address |
317 // -- sp[...]: constructor arguments | 346 // -- sp[...]: constructor arguments |
318 // ----------------------------------- | 347 // ----------------------------------- |
319 | 348 |
320 // Should never create mementos for api functions. | 349 // Should never create mementos for api functions. |
321 DCHECK(!is_api_function || !create_memento); | 350 DCHECK(!is_api_function || !create_memento); |
322 | 351 |
323 Isolate* isolate = masm->isolate(); | 352 Isolate* isolate = masm->isolate(); |
324 | 353 |
325 // Enter a construct frame. | 354 // Enter a construct frame. |
326 { | 355 { |
327 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | 356 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); |
328 | 357 |
329 if (create_memento) { | 358 if (create_memento) { |
330 __ AssertUndefinedOrAllocationSite(r5, r6); | 359 __ AssertUndefinedOrAllocationSite(r5, r7); |
331 __ push(r5); | 360 __ push(r5); |
332 } | 361 } |
333 | 362 |
334 // Preserve the two incoming parameters on the stack. | 363 // Preserve the two incoming parameters on the stack. |
335 __ SmiTag(r3); | 364 __ SmiTag(r3); |
336 __ push(r3); // Smi-tagged arguments count. | 365 __ Push(r3, r4); |
337 __ push(r4); // Constructor function. | 366 |
| 367 Label rt_call, allocated, normal_new, count_incremented; |
| 368 __ cmp(r4, r6); |
| 369 __ beq(&normal_new); |
| 370 |
| 371 // Original constructor and function are different. |
| 372 Generate_Runtime_NewObject(masm, create_memento, r6, &count_incremented, |
| 373 &allocated); |
| 374 __ bind(&normal_new); |
338 | 375 |
339 // Try to allocate the object without transitioning into C code. If any of | 376 // Try to allocate the object without transitioning into C code. If any of |
340 // the preconditions is not met, the code bails out to the runtime call. | 377 // the preconditions is not met, the code bails out to the runtime call. |
341 Label rt_call, allocated; | |
342 if (FLAG_inline_new) { | 378 if (FLAG_inline_new) { |
343 Label undo_allocation; | 379 Label undo_allocation; |
344 ExternalReference debug_step_in_fp = | 380 ExternalReference debug_step_in_fp = |
345 ExternalReference::debug_step_in_fp_address(isolate); | 381 ExternalReference::debug_step_in_fp_address(isolate); |
346 __ mov(r5, Operand(debug_step_in_fp)); | 382 __ mov(r5, Operand(debug_step_in_fp)); |
347 __ LoadP(r5, MemOperand(r5)); | 383 __ LoadP(r5, MemOperand(r5)); |
348 __ cmpi(r5, Operand::Zero()); | 384 __ cmpi(r5, Operand::Zero()); |
349 __ bne(&rt_call); | 385 __ bne(&rt_call); |
350 | 386 |
351 // Load the initial map and verify that it is in fact a map. | 387 // Load the initial map and verify that it is in fact a map. |
(...skipping 10 matching lines...) Expand all Loading... |
362 // r4: constructor function | 398 // r4: constructor function |
363 // r5: initial map | 399 // r5: initial map |
364 __ CompareInstanceType(r5, r6, JS_FUNCTION_TYPE); | 400 __ CompareInstanceType(r5, r6, JS_FUNCTION_TYPE); |
365 __ beq(&rt_call); | 401 __ beq(&rt_call); |
366 | 402 |
367 if (!is_api_function) { | 403 if (!is_api_function) { |
368 Label allocate; | 404 Label allocate; |
369 MemOperand bit_field3 = FieldMemOperand(r5, Map::kBitField3Offset); | 405 MemOperand bit_field3 = FieldMemOperand(r5, Map::kBitField3Offset); |
370 // Check if slack tracking is enabled. | 406 // Check if slack tracking is enabled. |
371 __ lwz(r7, bit_field3); | 407 __ lwz(r7, bit_field3); |
372 __ DecodeField<Map::ConstructionCount>(r11, r7); | 408 __ DecodeField<Map::Counter>(r11, r7); |
373 STATIC_ASSERT(JSFunction::kNoSlackTracking == 0); | 409 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
374 __ cmpi(r11, Operand::Zero()); // JSFunction::kNoSlackTracking | 410 __ blt(&allocate); |
375 __ beq(&allocate); | |
376 // Decrease generous allocation count. | 411 // Decrease generous allocation count. |
377 __ Add(r7, r7, -(1 << Map::ConstructionCount::kShift), r0); | 412 __ Add(r7, r7, -(1 << Map::Counter::kShift), r0); |
378 __ stw(r7, bit_field3); | 413 __ stw(r7, bit_field3); |
379 __ cmpi(r11, Operand(JSFunction::kFinishSlackTracking)); | 414 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
380 __ bne(&allocate); | 415 __ bne(&allocate); |
381 | 416 |
382 __ push(r4); | 417 __ push(r4); |
383 | 418 |
384 __ Push(r5, r4); // r4 = constructor | 419 __ Push(r5, r4); // r4 = constructor |
385 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | 420 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
386 | 421 |
387 __ Pop(r4, r5); | 422 __ Pop(r4, r5); |
388 | 423 |
389 __ bind(&allocate); | 424 __ bind(&allocate); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 // r7: JSObject (not tagged) | 457 // r7: JSObject (not tagged) |
423 // r8: First in-object property of JSObject (not tagged) | 458 // r8: First in-object property of JSObject (not tagged) |
424 // r9: End of object | 459 // r9: End of object |
425 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize); | 460 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize); |
426 __ LoadRoot(r10, Heap::kUndefinedValueRootIndex); | 461 __ LoadRoot(r10, Heap::kUndefinedValueRootIndex); |
427 | 462 |
428 if (!is_api_function) { | 463 if (!is_api_function) { |
429 Label no_inobject_slack_tracking; | 464 Label no_inobject_slack_tracking; |
430 | 465 |
431 // Check if slack tracking is enabled. | 466 // Check if slack tracking is enabled. |
432 STATIC_ASSERT(JSFunction::kNoSlackTracking == 0); | 467 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
433 __ cmpi(r11, Operand::Zero()); // JSFunction::kNoSlackTracking | 468 __ blt(&no_inobject_slack_tracking); |
434 __ beq(&no_inobject_slack_tracking); | |
435 | 469 |
436 // Allocate object with a slack. | 470 // Allocate object with a slack. |
437 __ lbz(r3, FieldMemOperand(r5, Map::kPreAllocatedPropertyFieldsOffset)); | 471 __ lbz(r3, FieldMemOperand(r5, Map::kPreAllocatedPropertyFieldsOffset)); |
438 if (FLAG_debug_code) { | 472 if (FLAG_debug_code) { |
439 __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); | 473 __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); |
440 __ add(r0, r8, r0); | 474 __ add(r0, r8, r0); |
441 // r0: offset of first field after pre-allocated fields | 475 // r0: offset of first field after pre-allocated fields |
442 __ cmp(r0, r9); | 476 __ cmp(r0, r9); |
443 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); | 477 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); |
444 } | 478 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 // example, the map's unused properties potentially do not match the | 595 // example, the map's unused properties potentially do not match the |
562 // allocated objects unused properties. | 596 // allocated objects unused properties. |
563 // r7: JSObject (previous new top) | 597 // r7: JSObject (previous new top) |
564 __ bind(&undo_allocation); | 598 __ bind(&undo_allocation); |
565 __ UndoAllocationInNewSpace(r7, r8); | 599 __ UndoAllocationInNewSpace(r7, r8); |
566 } | 600 } |
567 | 601 |
568 // Allocate the new receiver object using the runtime call. | 602 // Allocate the new receiver object using the runtime call. |
569 // r4: constructor function | 603 // r4: constructor function |
570 __ bind(&rt_call); | 604 __ bind(&rt_call); |
571 if (create_memento) { | 605 Generate_Runtime_NewObject(masm, create_memento, r4, &count_incremented, |
572 // Get the cell or allocation site. | 606 &allocated); |
573 __ LoadP(r5, MemOperand(sp, 2 * kPointerSize)); | |
574 __ push(r5); | |
575 } | |
576 | |
577 __ push(r4); // argument for Runtime_NewObject | |
578 if (create_memento) { | |
579 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 2); | |
580 } else { | |
581 __ CallRuntime(Runtime::kNewObject, 1); | |
582 } | |
583 __ mr(r7, r3); | |
584 | |
585 // If we ended up using the runtime, and we want a memento, then the | |
586 // runtime call made it for us, and we shouldn't do create count | |
587 // increment. | |
588 Label count_incremented; | |
589 if (create_memento) { | |
590 __ b(&count_incremented); | |
591 } | |
592 | 607 |
593 // Receiver for constructor call allocated. | 608 // Receiver for constructor call allocated. |
594 // r7: JSObject | 609 // r7: JSObject |
595 __ bind(&allocated); | 610 __ bind(&allocated); |
596 | 611 |
597 if (create_memento) { | 612 if (create_memento) { |
598 __ LoadP(r5, MemOperand(sp, kPointerSize * 2)); | 613 __ LoadP(r5, MemOperand(sp, kPointerSize * 2)); |
599 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); | 614 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); |
600 __ cmp(r5, r8); | 615 __ cmp(r5, r8); |
601 __ beq(&count_incremented); | 616 __ beq(&count_incremented); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 731 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
717 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 732 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); |
718 } | 733 } |
719 | 734 |
720 | 735 |
721 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 736 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
722 Generate_JSConstructStubHelper(masm, true, false); | 737 Generate_JSConstructStubHelper(masm, true, false); |
723 } | 738 } |
724 | 739 |
725 | 740 |
| 741 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
| 742 // ----------- S t a t e ------------- |
| 743 // -- r3 : number of arguments |
| 744 // -- r4 : constructor function |
| 745 // -- r5 : allocation site or undefined |
| 746 // -- r6 : original constructor |
| 747 // -- lr : return address |
| 748 // -- sp[...]: constructor arguments |
| 749 // ----------------------------------- |
| 750 |
| 751 // TODO(dslomov): support pretenuring |
| 752 CHECK(!FLAG_pretenuring_call_new); |
| 753 |
| 754 { |
| 755 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); |
| 756 |
| 757 // Smi-tagged arguments count. |
| 758 __ mr(r7, r3); |
| 759 __ SmiTag(r7, SetRC); |
| 760 |
| 761 // receiver is the hole. |
| 762 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 763 __ Push(r7, ip); |
| 764 |
| 765 // Set up pointer to last argument. |
| 766 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 767 |
| 768 // Copy arguments and receiver to the expression stack. |
| 769 // r3: number of arguments |
| 770 // r4: constructor function |
| 771 // r5: address of last argument (caller sp) |
| 772 // r7: number of arguments (smi-tagged) |
| 773 // cr0: compare against zero of arguments |
| 774 // sp[0]: receiver |
| 775 // sp[1]: number of arguments (smi-tagged) |
| 776 Label loop, no_args; |
| 777 __ beq(&no_args, cr0); |
| 778 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); |
| 779 __ mtctr(r3); |
| 780 __ bind(&loop); |
| 781 __ subi(ip, ip, Operand(kPointerSize)); |
| 782 __ LoadPX(r0, MemOperand(r5, ip)); |
| 783 __ push(r0); |
| 784 __ bdnz(&loop); |
| 785 __ bind(&no_args); |
| 786 |
| 787 // Call the function. |
| 788 // r3: number of arguments |
| 789 // r4: constructor function |
| 790 ParameterCount actual(r3); |
| 791 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); |
| 792 |
| 793 // Restore context from the frame. |
| 794 // r3: result |
| 795 // sp[0]: number of arguments (smi-tagged) |
| 796 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 797 __ LoadP(r4, MemOperand(sp, 0)); |
| 798 |
| 799 // Leave construct frame. |
| 800 } |
| 801 |
| 802 __ SmiToPtrArrayOffset(r4, r4); |
| 803 __ add(sp, sp, r4); |
| 804 __ addi(sp, sp, Operand(kPointerSize)); |
| 805 __ blr(); |
| 806 } |
| 807 |
| 808 |
726 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 809 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
727 bool is_construct) { | 810 bool is_construct) { |
728 // Called from Generate_JS_Entry | 811 // Called from Generate_JS_Entry |
729 // r3: code entry | 812 // r3: code entry |
730 // r4: function | 813 // r4: function |
731 // r5: receiver | 814 // r5: receiver |
732 // r6: argc | 815 // r6: argc |
733 // r7: argv | 816 // r7: argv |
734 // r0,r8-r9, cp may be clobbered | 817 // r0,r8-r9, cp may be clobbered |
735 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 818 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
(...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1606 __ bkpt(0); | 1689 __ bkpt(0); |
1607 } | 1690 } |
1608 } | 1691 } |
1609 | 1692 |
1610 | 1693 |
1611 #undef __ | 1694 #undef __ |
1612 } | 1695 } |
1613 } // namespace v8::internal | 1696 } // namespace v8::internal |
1614 | 1697 |
1615 #endif // V8_TARGET_ARCH_PPC | 1698 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |