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

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

Powered by Google App Engine
This is Rietveld 408576698