Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: src/ppc/builtins-ppc.cc

Issue 1465643002: PPC: Introduce a BuiltinsConstructStub that sets up new.target and does a [[call]] per ES6 9.3.2 (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698