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 #if V8_TARGET_ARCH_PPC | 5 #if V8_TARGET_ARCH_PPC |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.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 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 | 343 |
344 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 344 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
345 GenerateTailCallToReturnedCode(masm); | 345 GenerateTailCallToReturnedCode(masm); |
346 | 346 |
347 __ bind(&ok); | 347 __ bind(&ok); |
348 GenerateTailCallToSharedCode(masm); | 348 GenerateTailCallToSharedCode(masm); |
349 } | 349 } |
350 | 350 |
351 | 351 |
352 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 352 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
353 bool is_api_function) { | 353 bool is_api_function, |
| 354 bool create_implicit_receiver) { |
354 // ----------- S t a t e ------------- | 355 // ----------- S t a t e ------------- |
355 // -- r3 : number of arguments | 356 // -- r3 : number of arguments |
356 // -- r4 : constructor function | 357 // -- r4 : constructor function |
357 // -- r5 : allocation site or undefined | 358 // -- r5 : allocation site or undefined |
358 // -- r6 : new target | 359 // -- r6 : new target |
359 // -- lr : return address | 360 // -- lr : return address |
360 // -- sp[...]: constructor arguments | 361 // -- sp[...]: constructor arguments |
361 // ----------------------------------- | 362 // ----------------------------------- |
362 | 363 |
363 Isolate* isolate = masm->isolate(); | 364 Isolate* isolate = masm->isolate(); |
364 | 365 |
365 // Enter a construct frame. | 366 // Enter a construct frame. |
366 { | 367 { |
367 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | 368 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); |
368 | 369 |
369 // Preserve the incoming parameters on the stack. | 370 // Preserve the incoming parameters on the stack. |
370 __ AssertUndefinedOrAllocationSite(r5, r7); | 371 __ AssertUndefinedOrAllocationSite(r5, r7); |
371 __ SmiTag(r3); | |
372 __ Push(r5, r3, r4, r6); | |
373 | 372 |
374 // Try to allocate the object without transitioning into C code. If any of | 373 if (!create_implicit_receiver) { |
375 // the preconditions is not met, the code bails out to the runtime call. | 374 // Push new.target onto the construct frame. This is stored just below the |
376 Label rt_call, allocated; | 375 // receiver on the stack. |
377 if (FLAG_inline_new) { | 376 __ SmiTag(r7, r3, SetRC); |
378 // Verify that the new target is a JSFunction. | 377 __ Push(r5, r7, r6); |
379 __ CompareObjectType(r6, r8, r7, JS_FUNCTION_TYPE); | 378 __ PushRoot(Heap::kTheHoleValueRootIndex); |
380 __ bne(&rt_call); | 379 } else { |
| 380 __ SmiTag(r3); |
| 381 __ Push(r5, r3, r4, r6); |
381 | 382 |
382 // Load the initial map and verify that it is in fact a map. | 383 // Try to allocate the object without transitioning into C code. If any of |
383 // r6: new target | 384 // the preconditions is not met, the code bails out to the runtime call. |
384 __ LoadP(r5, | 385 Label rt_call, allocated; |
385 FieldMemOperand(r6, JSFunction::kPrototypeOrInitialMapOffset)); | 386 if (FLAG_inline_new) { |
386 __ JumpIfSmi(r5, &rt_call); | 387 // Verify that the new target is a JSFunction. |
387 __ CompareObjectType(r5, r8, r7, MAP_TYPE); | 388 __ CompareObjectType(r6, r8, r7, JS_FUNCTION_TYPE); |
388 __ bne(&rt_call); | 389 __ bne(&rt_call); |
389 | 390 |
390 // Fall back to runtime if the expected base constructor and base | 391 // Load the initial map and verify that it is in fact a map. |
391 // constructor differ. | 392 // r6: new target |
392 __ LoadP(r8, FieldMemOperand(r5, Map::kConstructorOrBackPointerOffset)); | 393 __ LoadP(r5, |
393 __ cmp(r4, r8); | 394 FieldMemOperand(r6, JSFunction::kPrototypeOrInitialMapOffset)); |
394 __ bne(&rt_call); | 395 __ JumpIfSmi(r5, &rt_call); |
| 396 __ CompareObjectType(r5, r8, r7, MAP_TYPE); |
| 397 __ bne(&rt_call); |
395 | 398 |
396 // Check that the constructor is not constructing a JSFunction (see | 399 // Fall back to runtime if the expected base constructor and base |
397 // comments in Runtime_NewObject in runtime.cc). In which case the | 400 // constructor differ. |
398 // initial map's instance type would be JS_FUNCTION_TYPE. | 401 __ LoadP(r8, FieldMemOperand(r5, Map::kConstructorOrBackPointerOffset)); |
399 // r4: constructor function | 402 __ cmp(r4, r8); |
400 // r5: initial map | 403 __ bne(&rt_call); |
401 __ CompareInstanceType(r5, r8, JS_FUNCTION_TYPE); | |
402 __ beq(&rt_call); | |
403 | 404 |
404 if (!is_api_function) { | 405 // Check that the constructor is not constructing a JSFunction (see |
405 Label allocate; | 406 // comments in Runtime_NewObject in runtime.cc). In which case the |
406 MemOperand bit_field3 = FieldMemOperand(r5, Map::kBitField3Offset); | 407 // initial map's instance type would be JS_FUNCTION_TYPE. |
407 // Check if slack tracking is enabled. | 408 // r4: constructor function |
408 __ lwz(r7, bit_field3); | 409 // r5: initial map |
409 __ DecodeField<Map::Counter>(r11, r7); | 410 __ CompareInstanceType(r5, r8, JS_FUNCTION_TYPE); |
410 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); | 411 __ beq(&rt_call); |
411 __ blt(&allocate); | |
412 // Decrease generous allocation count. | |
413 __ Add(r7, r7, -(1 << Map::Counter::kShift), r0); | |
414 __ stw(r7, bit_field3); | |
415 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); | |
416 __ bne(&allocate); | |
417 | 412 |
418 __ Push(r4, r5, r5); // r5 = initial map | 413 if (!is_api_function) { |
419 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | 414 Label allocate; |
| 415 MemOperand bit_field3 = FieldMemOperand(r5, Map::kBitField3Offset); |
| 416 // Check if slack tracking is enabled. |
| 417 __ lwz(r7, bit_field3); |
| 418 __ DecodeField<Map::Counter>(r11, r7); |
| 419 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
| 420 __ blt(&allocate); |
| 421 // Decrease generous allocation count. |
| 422 __ Add(r7, r7, -(1 << Map::Counter::kShift), r0); |
| 423 __ stw(r7, bit_field3); |
| 424 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
| 425 __ bne(&allocate); |
420 | 426 |
421 __ Pop(r4, r5); | 427 __ Push(r4, r5, r5); // r5 = initial map |
| 428 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
422 | 429 |
423 __ bind(&allocate); | 430 __ Pop(r4, r5); |
| 431 |
| 432 __ bind(&allocate); |
| 433 } |
| 434 |
| 435 // Now allocate the JSObject on the heap. |
| 436 // r4: constructor function |
| 437 // r5: initial map |
| 438 Label rt_call_reload_new_target; |
| 439 __ lbz(r6, FieldMemOperand(r5, Map::kInstanceSizeOffset)); |
| 440 |
| 441 __ Allocate(r6, r7, r8, r9, &rt_call_reload_new_target, SIZE_IN_WORDS); |
| 442 |
| 443 // Allocated the JSObject, now initialize the fields. Map is set to |
| 444 // initial map and properties and elements are set to empty fixed array. |
| 445 // r4: constructor function |
| 446 // r5: initial map |
| 447 // r6: object size |
| 448 // r7: JSObject (not tagged) |
| 449 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); |
| 450 __ mr(r8, r7); |
| 451 __ StoreP(r5, MemOperand(r8, JSObject::kMapOffset)); |
| 452 __ StoreP(r9, MemOperand(r8, JSObject::kPropertiesOffset)); |
| 453 __ StoreP(r9, MemOperand(r8, JSObject::kElementsOffset)); |
| 454 __ addi(r8, r8, Operand(JSObject::kElementsOffset + kPointerSize)); |
| 455 |
| 456 __ ShiftLeftImm(r9, r6, Operand(kPointerSizeLog2)); |
| 457 __ add(r9, r7, r9); // End of object. |
| 458 |
| 459 // Fill all the in-object properties with the appropriate filler. |
| 460 // r4: constructor function |
| 461 // r5: initial map |
| 462 // r6: object size |
| 463 // r7: JSObject (not tagged) |
| 464 // r8: First in-object property of JSObject (not tagged) |
| 465 // r9: End of object |
| 466 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize); |
| 467 __ LoadRoot(r10, Heap::kUndefinedValueRootIndex); |
| 468 |
| 469 if (!is_api_function) { |
| 470 Label no_inobject_slack_tracking; |
| 471 |
| 472 // Check if slack tracking is enabled. |
| 473 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
| 474 __ blt(&no_inobject_slack_tracking); |
| 475 |
| 476 // Allocate object with a slack. |
| 477 __ lbz(r3, |
| 478 FieldMemOperand( |
| 479 r5, |
| 480 Map::kInObjectPropertiesOrConstructorFunctionIndexOffset)); |
| 481 __ lbz(r5, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset)); |
| 482 __ sub(r3, r3, r5); |
| 483 if (FLAG_debug_code) { |
| 484 __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); |
| 485 __ add(r0, r8, r0); |
| 486 // r0: offset of first field after pre-allocated fields |
| 487 __ cmp(r0, r9); |
| 488 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); |
| 489 } |
| 490 { |
| 491 Label done; |
| 492 __ cmpi(r3, Operand::Zero()); |
| 493 __ beq(&done); |
| 494 __ InitializeNFieldsWithFiller(r8, r3, r10); |
| 495 __ bind(&done); |
| 496 } |
| 497 // To allow for truncation. |
| 498 __ LoadRoot(r10, Heap::kOnePointerFillerMapRootIndex); |
| 499 // Fill the remaining fields with one pointer filler map. |
| 500 |
| 501 __ bind(&no_inobject_slack_tracking); |
| 502 } |
| 503 |
| 504 __ InitializeFieldsWithFiller(r8, r9, r10); |
| 505 |
| 506 // Add the object tag to make the JSObject real, so that we can continue |
| 507 // and jump into the continuation code at any time from now on. |
| 508 __ addi(r7, r7, Operand(kHeapObjectTag)); |
| 509 |
| 510 // Continue with JSObject being successfully allocated |
| 511 // r7: JSObject |
| 512 __ b(&allocated); |
| 513 |
| 514 // Reload the new target and fall-through. |
| 515 __ bind(&rt_call_reload_new_target); |
| 516 __ LoadP(r6, MemOperand(sp, 0 * kPointerSize)); |
424 } | 517 } |
425 | 518 |
426 // Now allocate the JSObject on the heap. | 519 // Allocate the new receiver object using the runtime call. |
427 // r4: constructor function | 520 // r4: constructor function |
428 // r5: initial map | 521 // r6: new target |
429 Label rt_call_reload_new_target; | 522 __ bind(&rt_call); |
430 __ lbz(r6, FieldMemOperand(r5, Map::kInstanceSizeOffset)); | 523 __ Push(r4, r6); // constructor function, new target |
| 524 __ CallRuntime(Runtime::kNewObject, 2); |
| 525 __ mr(r7, r3); |
431 | 526 |
432 __ Allocate(r6, r7, r8, r9, &rt_call_reload_new_target, SIZE_IN_WORDS); | 527 // Receiver for constructor call allocated. |
| 528 // r7: JSObject |
| 529 __ bind(&allocated); |
433 | 530 |
434 // Allocated the JSObject, now initialize the fields. Map is set to | 531 // Restore the parameters. |
435 // initial map and properties and elements are set to empty fixed array. | 532 __ Pop(r4, r6); |
436 // r4: constructor function | |
437 // r5: initial map | |
438 // r6: object size | |
439 // r7: JSObject (not tagged) | |
440 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); | |
441 __ mr(r8, r7); | |
442 __ StoreP(r5, MemOperand(r8, JSObject::kMapOffset)); | |
443 __ StoreP(r9, MemOperand(r8, JSObject::kPropertiesOffset)); | |
444 __ StoreP(r9, MemOperand(r8, JSObject::kElementsOffset)); | |
445 __ addi(r8, r8, Operand(JSObject::kElementsOffset + kPointerSize)); | |
446 | 533 |
447 __ ShiftLeftImm(r9, r6, Operand(kPointerSizeLog2)); | 534 // Retrieve smi-tagged arguments count from the stack. |
448 __ add(r9, r7, r9); // End of object. | 535 __ LoadP(r3, MemOperand(sp)); |
| 536 __ SmiUntag(r3, SetRC); |
449 | 537 |
450 // Fill all the in-object properties with the appropriate filler. | 538 // Push new.target onto the construct frame. This is stored just below the |
451 // r4: constructor function | 539 // receiver on the stack. |
452 // r5: initial map | 540 // Push the allocated receiver to the stack. We need two copies |
453 // r6: object size | 541 // because we may have to return the original one and the calling |
454 // r7: JSObject (not tagged) | 542 // conventions dictate that the called function pops the receiver. |
455 // r8: First in-object property of JSObject (not tagged) | 543 __ Push(r6, r7, r7); |
456 // r9: End of object | |
457 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize); | |
458 __ LoadRoot(r10, Heap::kUndefinedValueRootIndex); | |
459 | |
460 if (!is_api_function) { | |
461 Label no_inobject_slack_tracking; | |
462 | |
463 // Check if slack tracking is enabled. | |
464 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); | |
465 __ blt(&no_inobject_slack_tracking); | |
466 | |
467 // Allocate object with a slack. | |
468 __ lbz( | |
469 r3, | |
470 FieldMemOperand( | |
471 r5, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset)); | |
472 __ lbz(r5, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset)); | |
473 __ sub(r3, r3, r5); | |
474 if (FLAG_debug_code) { | |
475 __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); | |
476 __ add(r0, r8, r0); | |
477 // r0: offset of first field after pre-allocated fields | |
478 __ cmp(r0, r9); | |
479 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); | |
480 } | |
481 { | |
482 Label done; | |
483 __ cmpi(r3, Operand::Zero()); | |
484 __ beq(&done); | |
485 __ InitializeNFieldsWithFiller(r8, r3, r10); | |
486 __ bind(&done); | |
487 } | |
488 // To allow for truncation. | |
489 __ LoadRoot(r10, Heap::kOnePointerFillerMapRootIndex); | |
490 // Fill the remaining fields with one pointer filler map. | |
491 | |
492 __ bind(&no_inobject_slack_tracking); | |
493 } | |
494 | |
495 __ InitializeFieldsWithFiller(r8, r9, r10); | |
496 | |
497 // Add the object tag to make the JSObject real, so that we can continue | |
498 // and jump into the continuation code at any time from now on. | |
499 __ addi(r7, r7, Operand(kHeapObjectTag)); | |
500 | |
501 // Continue with JSObject being successfully allocated | |
502 // r7: JSObject | |
503 __ b(&allocated); | |
504 | |
505 // Reload the new target and fall-through. | |
506 __ bind(&rt_call_reload_new_target); | |
507 __ LoadP(r6, MemOperand(sp, 0 * kPointerSize)); | |
508 } | 544 } |
509 | 545 |
510 // Allocate the new receiver object using the runtime call. | |
511 // r4: constructor function | |
512 // r6: new target | |
513 __ bind(&rt_call); | |
514 __ Push(r4, r6); // constructor function, new target | |
515 __ CallRuntime(Runtime::kNewObject, 2); | |
516 __ mr(r7, r3); | |
517 | |
518 // Receiver for constructor call allocated. | |
519 // r7: JSObject | |
520 __ bind(&allocated); | |
521 | |
522 // Restore the parameters. | |
523 __ Pop(r4, ip); | |
524 | |
525 // Retrieve smi-tagged arguments count from the stack. | |
526 __ LoadP(r6, MemOperand(sp)); | |
527 | |
528 // Push new.target onto the construct frame. This is stored just below the | |
529 // receiver on the stack. | |
530 __ Push(ip, r7, r7); | |
531 | |
532 // Set up pointer to last argument. | 546 // Set up pointer to last argument. |
533 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | 547 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
534 | 548 |
535 // Copy arguments and receiver to the expression stack. | 549 // Copy arguments and receiver to the expression stack. |
| 550 // r3: number of arguments |
536 // r4: constructor function | 551 // r4: constructor function |
537 // r5: address of last argument (caller sp) | 552 // r5: address of last argument (caller sp) |
538 // r6: number of arguments (smi-tagged) | 553 // cr0: condition indicating whether r3 is zero |
539 // sp[0]: receiver | 554 // sp[0]: receiver |
540 // sp[1]: receiver | 555 // sp[1]: receiver |
541 // sp[2]: new.target | 556 // sp[2]: new.target |
542 // sp[3]: number of arguments (smi-tagged) | 557 // sp[3]: number of arguments (smi-tagged) |
543 Label loop, no_args; | 558 Label loop, no_args; |
544 __ SmiUntag(r3, r6, SetRC); | |
545 __ beq(&no_args, cr0); | 559 __ beq(&no_args, cr0); |
546 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); | 560 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); |
547 __ sub(sp, sp, ip); | 561 __ sub(sp, sp, ip); |
548 __ mtctr(r3); | 562 __ mtctr(r3); |
549 __ bind(&loop); | 563 __ bind(&loop); |
550 __ subi(ip, ip, Operand(kPointerSize)); | 564 __ subi(ip, ip, Operand(kPointerSize)); |
551 __ LoadPX(r0, MemOperand(r5, ip)); | 565 __ LoadPX(r0, MemOperand(r5, ip)); |
552 __ StorePX(r0, MemOperand(sp, ip)); | 566 __ StorePX(r0, MemOperand(sp, ip)); |
553 __ bdnz(&loop); | 567 __ bdnz(&loop); |
554 __ bind(&no_args); | 568 __ bind(&no_args); |
555 | 569 |
556 // Call the function. | 570 // Call the function. |
557 // r3: number of arguments | 571 // r3: number of arguments |
558 // r4: constructor function | 572 // r4: constructor function |
559 if (is_api_function) { | 573 if (is_api_function) { |
560 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); | 574 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); |
561 Handle<Code> code = masm->isolate()->builtins()->HandleApiCallConstruct(); | 575 Handle<Code> code = masm->isolate()->builtins()->HandleApiCallConstruct(); |
562 __ Call(code, RelocInfo::CODE_TARGET); | 576 __ Call(code, RelocInfo::CODE_TARGET); |
563 } else { | 577 } else { |
564 ParameterCount actual(r3); | 578 ParameterCount actual(r3); |
565 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); | 579 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); |
566 } | 580 } |
567 | 581 |
568 // Store offset of return address for deoptimizer. | 582 // Store offset of return address for deoptimizer. |
569 if (!is_api_function) { | 583 if (create_implicit_receiver && !is_api_function) { |
570 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 584 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
571 } | 585 } |
572 | 586 |
573 // Restore context from the frame. | 587 // Restore context from the frame. |
574 // r3: result | 588 // r3: result |
575 // sp[0]: receiver | 589 // sp[0]: receiver |
576 // sp[1]: new.target | 590 // sp[1]: new.target |
577 // sp[2]: number of arguments (smi-tagged) | 591 // sp[2]: number of arguments (smi-tagged) |
578 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 592 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
579 | 593 |
580 // If the result is an object (in the ECMA sense), we should get rid | 594 if (create_implicit_receiver) { |
581 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 595 // If the result is an object (in the ECMA sense), we should get rid |
582 // on page 74. | 596 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
583 Label use_receiver, exit; | 597 // on page 74. |
| 598 Label use_receiver, exit; |
584 | 599 |
585 // If the result is a smi, it is *not* an object in the ECMA sense. | 600 // If the result is a smi, it is *not* an object in the ECMA sense. |
586 // r3: result | 601 // r3: result |
587 // sp[0]: receiver | 602 // sp[0]: receiver |
588 // sp[1]: new.target | 603 // sp[1]: new.target |
589 // sp[2]: number of arguments (smi-tagged) | 604 // sp[2]: number of arguments (smi-tagged) |
590 __ JumpIfSmi(r3, &use_receiver); | 605 __ JumpIfSmi(r3, &use_receiver); |
591 | 606 |
592 // If the type of the result (stored in its map) is less than | 607 // If the type of the result (stored in its map) is less than |
593 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 608 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
594 __ CompareObjectType(r3, r4, r6, FIRST_SPEC_OBJECT_TYPE); | 609 __ CompareObjectType(r3, r4, r6, FIRST_SPEC_OBJECT_TYPE); |
595 __ bge(&exit); | 610 __ bge(&exit); |
596 | 611 |
597 // Throw away the result of the constructor invocation and use the | 612 // Throw away the result of the constructor invocation and use the |
598 // on-stack receiver as the result. | 613 // on-stack receiver as the result. |
599 __ bind(&use_receiver); | 614 __ bind(&use_receiver); |
600 __ LoadP(r3, MemOperand(sp)); | 615 __ LoadP(r3, MemOperand(sp)); |
601 | 616 |
602 // Remove receiver from the stack, remove caller arguments, and | 617 // Remove receiver from the stack, remove caller arguments, and |
603 // return. | 618 // return. |
604 __ bind(&exit); | 619 __ bind(&exit); |
605 // r3: result | 620 // r3: result |
606 // sp[0]: receiver (newly allocated object) | 621 // sp[0]: receiver (newly allocated object) |
607 // sp[1]: new.target (new target) | 622 // sp[1]: new.target (new target) |
608 // sp[2]: number of arguments (smi-tagged) | 623 // sp[2]: number of arguments (smi-tagged) |
609 __ LoadP(r4, MemOperand(sp, 2 * kPointerSize)); | 624 __ LoadP(r4, MemOperand(sp, 2 * kPointerSize)); |
| 625 } else { |
| 626 __ LoadP(r4, MemOperand(sp, kPointerSize)); |
| 627 } |
610 | 628 |
611 // Leave construct frame. | 629 // Leave construct frame. |
612 } | 630 } |
613 | 631 |
614 __ SmiToPtrArrayOffset(r4, r4); | 632 __ SmiToPtrArrayOffset(r4, r4); |
615 __ add(sp, sp, r4); | 633 __ add(sp, sp, r4); |
616 __ addi(sp, sp, Operand(kPointerSize)); | 634 __ addi(sp, sp, Operand(kPointerSize)); |
617 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r4, r5); | 635 if (create_implicit_receiver) { |
| 636 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r4, r5); |
| 637 } |
618 __ blr(); | 638 __ blr(); |
619 } | 639 } |
620 | 640 |
621 | 641 |
622 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 642 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
623 Generate_JSConstructStubHelper(masm, false); | 643 Generate_JSConstructStubHelper(masm, false, true); |
624 } | 644 } |
625 | 645 |
626 | 646 |
627 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 647 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
628 Generate_JSConstructStubHelper(masm, true); | 648 Generate_JSConstructStubHelper(masm, true, true); |
629 } | 649 } |
630 | 650 |
631 | 651 |
632 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 652 void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) { |
633 // ----------- S t a t e ------------- | 653 Generate_JSConstructStubHelper(masm, false, false); |
634 // -- r3 : number of arguments | |
635 // -- r4 : constructor function | |
636 // -- r5 : allocation site or undefined | |
637 // -- r6 : new target | |
638 // -- lr : return address | |
639 // -- sp[...]: constructor arguments | |
640 // ----------------------------------- | |
641 | |
642 { | |
643 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | |
644 | |
645 __ AssertUndefinedOrAllocationSite(r5, r7); | |
646 | |
647 // Smi-tagged arguments count. | |
648 __ mr(r7, r3); | |
649 __ SmiTag(r7, SetRC); | |
650 | |
651 // receiver is the hole. | |
652 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
653 | |
654 // allocation site, smi arguments count, new.target, receiver | |
655 __ Push(r5, r7, r6, ip); | |
656 | |
657 // Set up pointer to last argument. | |
658 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | |
659 | |
660 // Copy arguments and receiver to the expression stack. | |
661 // r3: number of arguments | |
662 // r4: constructor function | |
663 // r5: address of last argument (caller sp) | |
664 // r7: number of arguments (smi-tagged) | |
665 // cr0: compare against zero of arguments | |
666 // sp[0]: receiver | |
667 // sp[1]: new.target | |
668 // sp[2]: number of arguments (smi-tagged) | |
669 Label loop, no_args; | |
670 __ beq(&no_args, cr0); | |
671 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); | |
672 __ mtctr(r3); | |
673 __ bind(&loop); | |
674 __ subi(ip, ip, Operand(kPointerSize)); | |
675 __ LoadPX(r0, MemOperand(r5, ip)); | |
676 __ push(r0); | |
677 __ bdnz(&loop); | |
678 __ bind(&no_args); | |
679 | |
680 // Call the function. | |
681 // r3: number of arguments | |
682 // r4: constructor function | |
683 ParameterCount actual(r3); | |
684 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); | |
685 | |
686 // Restore context from the frame. | |
687 // r3: result | |
688 // sp[0]: number of arguments (smi-tagged) | |
689 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
690 // Get arguments count, skipping over new.target. | |
691 __ LoadP(r4, MemOperand(sp, kPointerSize)); | |
692 | |
693 // Leave construct frame. | |
694 } | |
695 | |
696 __ SmiToPtrArrayOffset(r4, r4); | |
697 __ add(sp, sp, r4); | |
698 __ addi(sp, sp, Operand(kPointerSize)); | |
699 __ blr(); | |
700 } | 654 } |
701 | 655 |
702 | 656 |
703 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt }; | 657 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt }; |
704 | 658 |
705 | 659 |
706 // Clobbers r5; preserves all other registers. | 660 // Clobbers r5; preserves all other registers. |
707 static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, | 661 static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, |
708 IsTagged argc_is_tagged) { | 662 IsTagged argc_is_tagged) { |
709 // Check the stack for overflow. We are not trying to catch | 663 // Check the stack for overflow. We are not trying to catch |
(...skipping 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1925 __ bkpt(0); | 1879 __ bkpt(0); |
1926 } | 1880 } |
1927 } | 1881 } |
1928 | 1882 |
1929 | 1883 |
1930 #undef __ | 1884 #undef __ |
1931 } // namespace internal | 1885 } // namespace internal |
1932 } // namespace v8 | 1886 } // namespace v8 |
1933 | 1887 |
1934 #endif // V8_TARGET_ARCH_PPC | 1888 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |