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

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

Issue 1448933002: 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 | « src/mips/builtins-mips.cc ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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_MIPS64 5 #if V8_TARGET_ARCH_MIPS64
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 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 341
342 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); 342 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
343 GenerateTailCallToReturnedCode(masm); 343 GenerateTailCallToReturnedCode(masm);
344 344
345 __ bind(&ok); 345 __ bind(&ok);
346 GenerateTailCallToSharedCode(masm); 346 GenerateTailCallToSharedCode(masm);
347 } 347 }
348 348
349 349
350 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 350 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
351 bool is_api_function) { 351 bool is_api_function,
352 bool create_implicit_receiver) {
352 // ----------- S t a t e ------------- 353 // ----------- S t a t e -------------
353 // -- a0 : number of arguments 354 // -- a0 : number of arguments
354 // -- a1 : constructor function 355 // -- a1 : constructor function
355 // -- a2 : allocation site or undefined 356 // -- a2 : allocation site or undefined
356 // -- a3 : new target 357 // -- a3 : new target
357 // -- ra : return address 358 // -- ra : return address
358 // -- sp[...]: constructor arguments 359 // -- sp[...]: constructor arguments
359 // ----------------------------------- 360 // -----------------------------------
360 361
361 Isolate* isolate = masm->isolate(); 362 Isolate* isolate = masm->isolate();
362 363
363 // Enter a construct frame. 364 // Enter a construct frame.
364 { 365 {
365 FrameScope scope(masm, StackFrame::CONSTRUCT); 366 FrameScope scope(masm, StackFrame::CONSTRUCT);
366 367
367 // Preserve the incoming parameters on the stack. 368 // Preserve the incoming parameters on the stack.
368 __ AssertUndefinedOrAllocationSite(a2, t0); 369 __ AssertUndefinedOrAllocationSite(a2, t0);
369 __ SmiTag(a0); 370 __ SmiTag(a0);
370 __ Push(a2, a0, a1, a3); 371 if (create_implicit_receiver) {
372 __ Push(a2, a0, a1, a3);
373 } else {
374 __ Push(a2, a0);
375 }
371 376
372 // Try to allocate the object without transitioning into C code. If any of 377 if (create_implicit_receiver) {
373 // the preconditions is not met, the code bails out to the runtime call. 378 // Try to allocate the object without transitioning into C code. If any of
374 Label rt_call, allocated; 379 // the preconditions is not met, the code bails out to the runtime call.
375 if (FLAG_inline_new) { 380 Label rt_call, allocated;
376 // Verify that the new target is a JSFunction. 381 if (FLAG_inline_new) {
377 __ GetObjectType(a3, a5, a4); 382 // Verify that the new target is a JSFunction.
378 __ Branch(&rt_call, ne, a4, Operand(JS_FUNCTION_TYPE)); 383 __ GetObjectType(a3, a5, a4);
384 __ Branch(&rt_call, ne, a4, Operand(JS_FUNCTION_TYPE));
379 385
380 // Load the initial map and verify that it is in fact a map. 386 // Load the initial map and verify that it is in fact a map.
381 // a3: new target 387 // a3: new target
382 __ ld(a2, FieldMemOperand(a3, JSFunction::kPrototypeOrInitialMapOffset)); 388 __ ld(a2,
383 __ JumpIfSmi(a2, &rt_call); 389 FieldMemOperand(a3, JSFunction::kPrototypeOrInitialMapOffset));
384 __ GetObjectType(a2, t1, t0); 390 __ JumpIfSmi(a2, &rt_call);
385 __ Branch(&rt_call, ne, t0, Operand(MAP_TYPE)); 391 __ GetObjectType(a2, t1, t0);
392 __ Branch(&rt_call, ne, t0, Operand(MAP_TYPE));
386 393
387 // Fall back to runtime if the expected base constructor and base 394 // Fall back to runtime if the expected base constructor and base
388 // constructor differ. 395 // constructor differ.
389 __ ld(a5, FieldMemOperand(a2, Map::kConstructorOrBackPointerOffset)); 396 __ ld(a5, FieldMemOperand(a2, Map::kConstructorOrBackPointerOffset));
390 __ Branch(&rt_call, ne, a1, Operand(a5)); 397 __ Branch(&rt_call, ne, a1, Operand(a5));
391 398
392 // Check that the constructor is not constructing a JSFunction (see 399 // Check that the constructor is not constructing a JSFunction (see
393 // comments in Runtime_NewObject in runtime.cc). In which case the 400 // comments in Runtime_NewObject in runtime.cc). In which case the
394 // initial map's instance type would be JS_FUNCTION_TYPE. 401 // initial map's instance type would be JS_FUNCTION_TYPE.
395 // a1: constructor function 402 // a1: constructor function
396 // a2: initial map 403 // a2: initial map
397 __ lbu(t1, FieldMemOperand(a2, Map::kInstanceTypeOffset)); 404 __ lbu(t1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
398 __ Branch(&rt_call, eq, t1, Operand(JS_FUNCTION_TYPE)); 405 __ Branch(&rt_call, eq, t1, Operand(JS_FUNCTION_TYPE));
399 406
400 if (!is_api_function) { 407 if (!is_api_function) {
401 Label allocate; 408 Label allocate;
402 MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset); 409 MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset);
403 // Check if slack tracking is enabled. 410 // Check if slack tracking is enabled.
404 __ lwu(a4, bit_field3); 411 __ lwu(a4, bit_field3);
405 __ DecodeField<Map::Counter>(a6, a4); 412 __ DecodeField<Map::Counter>(a6, a4);
406 __ Branch(&allocate, lt, a6, 413 __ Branch(
407 Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd))); 414 &allocate, lt, a6,
408 // Decrease generous allocation count. 415 Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
409 __ Dsubu(a4, a4, Operand(1 << Map::Counter::kShift)); 416 // Decrease generous allocation count.
410 __ Branch(USE_DELAY_SLOT, &allocate, ne, a6, 417 __ Dsubu(a4, a4, Operand(1 << Map::Counter::kShift));
411 Operand(Map::kSlackTrackingCounterEnd)); 418 __ Branch(USE_DELAY_SLOT, &allocate, ne, a6,
412 __ sw(a4, bit_field3); // In delay slot. 419 Operand(Map::kSlackTrackingCounterEnd));
420 __ sw(a4, bit_field3); // In delay slot.
413 421
414 __ Push(a1, a2, a2); // a2 = Initial map. 422 __ Push(a1, a2, a2); // a2 = Initial map.
415 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 423 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
416 424
417 __ Pop(a1, a2); 425 __ Pop(a1, a2);
418 __ li(a6, Operand(Map::kSlackTrackingCounterEnd - 1)); 426 __ li(a6, Operand(Map::kSlackTrackingCounterEnd - 1));
419 427
420 __ bind(&allocate); 428 __ bind(&allocate);
429 }
430
431 // Now allocate the JSObject on the heap.
432 // a1: constructor function
433 // a2: initial map
434 Label rt_call_reload_new_target;
435 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
436
437 __ Allocate(a3, t0, t1, t2, &rt_call_reload_new_target, SIZE_IN_WORDS);
438
439 // Allocated the JSObject, now initialize the fields. Map is set to
440 // initial map and properties and elements are set to empty fixed array.
441 // a1: constructor function
442 // a2: initial map
443 // a3: object size
444 // t0: JSObject (not tagged)
445 __ LoadRoot(t2, Heap::kEmptyFixedArrayRootIndex);
446 __ mov(t1, t0);
447 __ sd(a2, MemOperand(t1, JSObject::kMapOffset));
448 __ sd(t2, MemOperand(t1, JSObject::kPropertiesOffset));
449 __ sd(t2, MemOperand(t1, JSObject::kElementsOffset));
450 __ Daddu(t1, t1, Operand(3 * kPointerSize));
451 DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
452 DCHECK_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
453 DCHECK_EQ(2 * kPointerSize, JSObject::kElementsOffset);
454
455 // Fill all the in-object properties with appropriate filler.
456 // a1: constructor function
457 // a2: initial map
458 // a3: object size (in words)
459 // t0: JSObject (not tagged)
460 // t1: First in-object property of JSObject (not tagged)
461 // a6: slack tracking counter (non-API function case)
462 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
463
464 // Use t3 to hold undefined, which is used in several places below.
465 __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
466
467 if (!is_api_function) {
468 Label no_inobject_slack_tracking;
469
470 // Check if slack tracking is enabled.
471 __ Branch(
472 &no_inobject_slack_tracking, lt, a6,
473 Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
474
475 // Allocate object with a slack.
476 __ lbu(a0,
477 FieldMemOperand(
478 a2,
479 Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
480 __ lbu(a2, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
481 __ dsubu(a0, a0, a2);
482 __ dsll(at, a0, kPointerSizeLog2);
483 __ daddu(a0, t1, at);
484 // a0: offset of first field after pre-allocated fields
485 if (FLAG_debug_code) {
486 __ dsll(at, a3, kPointerSizeLog2);
487 __ Daddu(t2, t0, Operand(at)); // End of object.
488 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields, a0,
489 Operand(t2));
490 }
491 __ InitializeFieldsWithFiller(t1, a0, t3);
492 // To allow for truncation.
493 __ LoadRoot(t3, Heap::kOnePointerFillerMapRootIndex);
494 // Fill the remaining fields with one pointer filler map.
495
496 __ bind(&no_inobject_slack_tracking);
497 }
498
499 __ dsll(at, a3, kPointerSizeLog2);
500 __ Daddu(a0, t0, Operand(at)); // End of object.
501 __ InitializeFieldsWithFiller(t1, a0, t3);
502
503 // Add the object tag to make the JSObject real, so that we can continue
504 // and jump into the continuation code at any time from now on.
505 __ Daddu(t0, t0, Operand(kHeapObjectTag));
506
507 // Continue with JSObject being successfully allocated.
508 // a4: JSObject
509 __ jmp(&allocated);
510
511 // Reload the new target and fall-through.
512 __ bind(&rt_call_reload_new_target);
513 __ ld(a3, MemOperand(sp, 0 * kPointerSize));
421 } 514 }
422 515
423 // Now allocate the JSObject on the heap. 516 // Allocate the new receiver object using the runtime call.
424 // a1: constructor function 517 // a1: constructor function
425 // a2: initial map 518 // a3: new target
426 Label rt_call_reload_new_target; 519 __ bind(&rt_call);
427 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
428 520
429 __ Allocate(a3, t0, t1, t2, &rt_call_reload_new_target, SIZE_IN_WORDS); 521 __ Push(a1, a3); // constructor function, new target
522 __ CallRuntime(Runtime::kNewObject, 2);
523 __ mov(t0, v0);
430 524
431 // Allocated the JSObject, now initialize the fields. Map is set to 525 // Receiver for constructor call allocated.
432 // initial map and properties and elements are set to empty fixed array. 526 // t0: JSObject
433 // a1: constructor function 527 __ bind(&allocated);
434 // a2: initial map
435 // a3: object size
436 // t0: JSObject (not tagged)
437 __ LoadRoot(t2, Heap::kEmptyFixedArrayRootIndex);
438 __ mov(t1, t0);
439 __ sd(a2, MemOperand(t1, JSObject::kMapOffset));
440 __ sd(t2, MemOperand(t1, JSObject::kPropertiesOffset));
441 __ sd(t2, MemOperand(t1, JSObject::kElementsOffset));
442 __ Daddu(t1, t1, Operand(3*kPointerSize));
443 DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
444 DCHECK_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
445 DCHECK_EQ(2 * kPointerSize, JSObject::kElementsOffset);
446 528
447 // Fill all the in-object properties with appropriate filler. 529 // Restore the parameters.
448 // a1: constructor function 530 __ Pop(a3); // new.target
449 // a2: initial map 531 __ Pop(a1);
450 // a3: object size (in words)
451 // t0: JSObject (not tagged)
452 // t1: First in-object property of JSObject (not tagged)
453 // a6: slack tracking counter (non-API function case)
454 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
455 532
456 // Use t3 to hold undefined, which is used in several places below. 533 __ ld(a0, MemOperand(sp));
457 __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
458
459 if (!is_api_function) {
460 Label no_inobject_slack_tracking;
461
462 // Check if slack tracking is enabled.
463 __ Branch(&no_inobject_slack_tracking, lt, a6,
464 Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
465
466 // Allocate object with a slack.
467 __ lbu(
468 a0,
469 FieldMemOperand(
470 a2, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
471 __ lbu(a2, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
472 __ dsubu(a0, a0, a2);
473 __ dsll(at, a0, kPointerSizeLog2);
474 __ daddu(a0, t1, at);
475 // a0: offset of first field after pre-allocated fields
476 if (FLAG_debug_code) {
477 __ dsll(at, a3, kPointerSizeLog2);
478 __ Daddu(t2, t0, Operand(at)); // End of object.
479 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields,
480 a0, Operand(t2));
481 }
482 __ InitializeFieldsWithFiller(t1, a0, t3);
483 // To allow for truncation.
484 __ LoadRoot(t3, Heap::kOnePointerFillerMapRootIndex);
485 // Fill the remaining fields with one pointer filler map.
486
487 __ bind(&no_inobject_slack_tracking);
488 }
489
490 __ dsll(at, a3, kPointerSizeLog2);
491 __ Daddu(a0, t0, Operand(at)); // End of object.
492 __ InitializeFieldsWithFiller(t1, a0, t3);
493
494 // Add the object tag to make the JSObject real, so that we can continue
495 // and jump into the continuation code at any time from now on.
496 __ Daddu(t0, t0, Operand(kHeapObjectTag));
497
498 // Continue with JSObject being successfully allocated.
499 // a4: JSObject
500 __ jmp(&allocated);
501
502 // Reload the new target and fall-through.
503 __ bind(&rt_call_reload_new_target);
504 __ ld(a3, MemOperand(sp, 0 * kPointerSize));
505 } 534 }
506
507 // Allocate the new receiver object using the runtime call.
508 // a1: constructor function
509 // a3: new target
510 __ bind(&rt_call);
511
512 __ Push(a1, a3); // constructor function, new target
513 __ CallRuntime(Runtime::kNewObject, 2);
514 __ mov(t0, v0);
515
516 // Receiver for constructor call allocated.
517 // t0: JSObject
518 __ bind(&allocated);
519
520 // Restore the parameters.
521 __ Pop(a3); // new.target
522 __ Pop(a1);
523
524 __ ld(a0, MemOperand(sp));
525 __ SmiUntag(a0); 535 __ SmiUntag(a0);
526 536
527 __ Push(a3, t0, t0); 537 // Push new.target onto the construct frame. This is stored just below the
538 // receiver on the stack.
539 if (create_implicit_receiver) {
540 // Push the allocated receiver to the stack. We need two copies
541 // because we may have to return the original one and the calling
542 // conventions dictate that the called function pops the receiver.
543 __ Push(a3, t0, t0);
544 } else {
545 __ push(a3);
546 __ PushRoot(Heap::kTheHoleValueRootIndex);
547 }
528 548
529 // Set up pointer to last argument. 549 // Set up pointer to last argument.
530 __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); 550 __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
531 551
532 // Copy arguments and receiver to the expression stack. 552 // Copy arguments and receiver to the expression stack.
533 // a0: number of arguments 553 // a0: number of arguments
534 // a1: constructor function 554 // a1: constructor function
535 // a2: address of last argument (caller sp) 555 // a2: address of last argument (caller sp)
536 // a3: number of arguments (smi-tagged) 556 // a3: number of arguments (smi-tagged)
537 // sp[0]: receiver 557 // sp[0]: receiver
(...skipping 19 matching lines...) Expand all
557 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 577 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
558 Handle<Code> code = 578 Handle<Code> code =
559 masm->isolate()->builtins()->HandleApiCallConstruct(); 579 masm->isolate()->builtins()->HandleApiCallConstruct();
560 __ Call(code, RelocInfo::CODE_TARGET); 580 __ Call(code, RelocInfo::CODE_TARGET);
561 } else { 581 } else {
562 ParameterCount actual(a0); 582 ParameterCount actual(a0);
563 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper()); 583 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
564 } 584 }
565 585
566 // Store offset of return address for deoptimizer. 586 // Store offset of return address for deoptimizer.
567 if (!is_api_function) { 587 if (create_implicit_receiver && !is_api_function) {
568 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 588 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
569 } 589 }
570 590
571 // Restore context from the frame. 591 // Restore context from the frame.
572 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 592 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
573 593
574 // If the result is an object (in the ECMA sense), we should get rid 594 if (create_implicit_receiver) {
575 // 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
576 // on page 74. 596 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
577 Label use_receiver, exit; 597 // on page 74.
598 Label use_receiver, exit;
578 599
579 // 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.
580 // v0: result 601 // v0: result
581 // sp[0]: receiver (newly allocated object) 602 // sp[0]: receiver (newly allocated object)
582 // sp[1]: new.target 603 // sp[1]: new.target
583 // sp[2]: number of arguments (smi-tagged) 604 // sp[2]: number of arguments (smi-tagged)
584 __ JumpIfSmi(v0, &use_receiver); 605 __ JumpIfSmi(v0, &use_receiver);
585 606
586 // 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
587 // 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.
588 __ GetObjectType(v0, a1, a3); 609 __ GetObjectType(v0, a1, a3);
589 __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); 610 __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
590 611
591 // Throw away the result of the constructor invocation and use the 612 // Throw away the result of the constructor invocation and use the
592 // on-stack receiver as the result. 613 // on-stack receiver as the result.
593 __ bind(&use_receiver); 614 __ bind(&use_receiver);
594 __ ld(v0, MemOperand(sp)); 615 __ ld(v0, MemOperand(sp));
595 616
596 // Remove receiver from the stack, remove caller arguments, and 617 // Remove receiver from the stack, remove caller arguments, and
597 // return. 618 // return.
598 __ bind(&exit); 619 __ bind(&exit);
599 // v0: result 620 // v0: result
600 // sp[0]: receiver (newly allocated object) 621 // sp[0]: receiver (newly allocated object)
601 // sp[1]: new target 622 // sp[1]: new target
602 // sp[2]: number of arguments (smi-tagged) 623 // sp[2]: number of arguments (smi-tagged)
603 __ ld(a1, MemOperand(sp, 2 * kPointerSize)); 624 __ ld(a1, MemOperand(sp, 2 * kPointerSize));
625 } else {
626 __ ld(a1, MemOperand(sp, kPointerSize));
627 }
604 628
605 // Leave construct frame. 629 // Leave construct frame.
606 } 630 }
607 631
608 __ SmiScale(a4, a1, kPointerSizeLog2); 632 __ SmiScale(a4, a1, kPointerSizeLog2);
609 __ Daddu(sp, sp, a4); 633 __ Daddu(sp, sp, a4);
610 __ Daddu(sp, sp, kPointerSize); 634 __ Daddu(sp, sp, kPointerSize);
611 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2); 635 if (create_implicit_receiver) {
636 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2);
637 }
612 __ Ret(); 638 __ Ret();
613 } 639 }
614 640
615 641
616 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 642 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
617 Generate_JSConstructStubHelper(masm, false); 643 Generate_JSConstructStubHelper(masm, false, true);
618 } 644 }
619 645
620 646
621 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 647 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
622 Generate_JSConstructStubHelper(masm, true); 648 Generate_JSConstructStubHelper(masm, true, true);
623 } 649 }
624 650
625 651
626 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { 652 void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
627 // ----------- S t a t e ------------- 653 Generate_JSConstructStubHelper(masm, false, false);
628 // -- a0 : number of arguments
629 // -- a1 : constructor function
630 // -- a2 : allocation site or undefined
631 // -- a3 : new target
632 // -- ra : return address
633 // -- sp[...]: constructor arguments
634 // -----------------------------------
635
636 {
637 FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
638
639 __ AssertUndefinedOrAllocationSite(a2, t0);
640 __ push(a2);
641
642 __ mov(a4, a0);
643 __ SmiTag(a4);
644 __ push(a4); // Smi-tagged arguments count.
645
646 // Push new.target.
647 __ push(a3);
648
649 // receiver is the hole.
650 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
651 __ push(at);
652
653 // Set up pointer to last argument.
654 __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
655
656 // Copy arguments and receiver to the expression stack.
657 // a0: number of arguments
658 // a1: constructor function
659 // a2: address of last argument (caller sp)
660 // a4: number of arguments (smi-tagged)
661 // sp[0]: receiver
662 // sp[1]: new.target
663 // sp[2]: number of arguments (smi-tagged)
664 Label loop, entry;
665 __ SmiUntag(a4);
666 __ jmp(&entry);
667 __ bind(&loop);
668 __ dsll(at, a4, kPointerSizeLog2);
669 __ Daddu(at, a2, Operand(at));
670 __ ld(at, MemOperand(at));
671 __ push(at);
672 __ bind(&entry);
673 __ Daddu(a4, a4, Operand(-1));
674 __ Branch(&loop, ge, a4, Operand(zero_reg));
675
676 // Call the function.
677 // a0: number of arguments
678 // a1: constructor function
679 ParameterCount actual(a0);
680 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
681
682 // Restore context from the frame.
683 // v0: result
684 // sp[0]: new.target
685 // sp[1]: number of arguments (smi-tagged)
686 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
687 __ ld(a1, MemOperand(sp, kPointerSize));
688
689 // Leave construct frame.
690 }
691
692 __ SmiScale(at, a1, kPointerSizeLog2);
693 __ Daddu(sp, sp, Operand(at));
694 __ Daddu(sp, sp, Operand(kPointerSize));
695 __ Jump(ra);
696 } 654 }
697 655
698 656
699 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt }; 657 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
700 658
701 659
702 // Clobbers a2; preserves all other registers. 660 // Clobbers a2; preserves all other registers.
703 static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, 661 static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc,
704 IsTagged argc_is_tagged) { 662 IsTagged argc_is_tagged) {
705 // Check the stack for overflow. We are not trying to catch 663 // Check the stack for overflow. We are not trying to catch
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1928 } 1886 }
1929 } 1887 }
1930 1888
1931 1889
1932 #undef __ 1890 #undef __
1933 1891
1934 } // namespace internal 1892 } // namespace internal
1935 } // namespace v8 1893 } // namespace v8
1936 1894
1937 #endif // V8_TARGET_ARCH_MIPS64 1895 #endif // V8_TARGET_ARCH_MIPS64
OLDNEW
« no previous file with comments | « src/mips/builtins-mips.cc ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698