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

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

Issue 1468073004: Reshuffle registers in JSConstructStub to avoid trashing costructor and new.target on fast path (so… (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years 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/macro-assembler-mips.cc ('k') | src/mips64/code-stubs-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_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 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 361
362 Isolate* isolate = masm->isolate(); 362 Isolate* isolate = masm->isolate();
363 363
364 // Enter a construct frame. 364 // Enter a construct frame.
365 { 365 {
366 FrameScope scope(masm, StackFrame::CONSTRUCT); 366 FrameScope scope(masm, StackFrame::CONSTRUCT);
367 367
368 // Preserve the incoming parameters on the stack. 368 // Preserve the incoming parameters on the stack.
369 __ AssertUndefinedOrAllocationSite(a2, t0); 369 __ AssertUndefinedOrAllocationSite(a2, t0);
370 __ SmiTag(a0); 370 __ SmiTag(a0);
371 if (create_implicit_receiver) { 371 __ Push(a2, a0);
372 __ Push(a2, a0, a1, a3);
373 } else {
374 __ Push(a2, a0);
375 }
376 372
377 if (create_implicit_receiver) { 373 if (create_implicit_receiver) {
378 // Try to allocate the object without transitioning into C code. If any of 374 // Try to allocate the object without transitioning into C code. If any of
379 // the preconditions is not met, the code bails out to the runtime call. 375 // the preconditions is not met, the code bails out to the runtime call.
380 Label rt_call, allocated; 376 Label rt_call, allocated;
381 if (FLAG_inline_new) { 377 if (FLAG_inline_new) {
382 // Verify that the new target is a JSFunction. 378 // Verify that the new target is a JSFunction.
383 __ GetObjectType(a3, a5, a4); 379 __ GetObjectType(a3, a5, a4);
384 __ Branch(&rt_call, ne, a4, Operand(JS_FUNCTION_TYPE)); 380 __ Branch(&rt_call, ne, a4, Operand(JS_FUNCTION_TYPE));
385 381
(...skipping 26 matching lines...) Expand all
412 __ DecodeField<Map::Counter>(a6, a4); 408 __ DecodeField<Map::Counter>(a6, a4);
413 __ Branch( 409 __ Branch(
414 &allocate, lt, a6, 410 &allocate, lt, a6,
415 Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd))); 411 Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
416 // Decrease generous allocation count. 412 // Decrease generous allocation count.
417 __ Dsubu(a4, a4, Operand(1 << Map::Counter::kShift)); 413 __ Dsubu(a4, a4, Operand(1 << Map::Counter::kShift));
418 __ Branch(USE_DELAY_SLOT, &allocate, ne, a6, 414 __ Branch(USE_DELAY_SLOT, &allocate, ne, a6,
419 Operand(Map::kSlackTrackingCounterEnd)); 415 Operand(Map::kSlackTrackingCounterEnd));
420 __ sw(a4, bit_field3); // In delay slot. 416 __ sw(a4, bit_field3); // In delay slot.
421 417
422 __ Push(a1, a2, a2); // a2 = Initial map. 418 // Push the constructor, new_target and map to the stack, and
419 // the map again as an argument to the runtime call.
420 __ Push(a1, a3, a2, a2);
423 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 421 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
424 422
425 __ Pop(a1, a2); 423 __ Pop(a1, a3, a2);
426 __ li(a6, Operand(Map::kSlackTrackingCounterEnd - 1)); 424 __ li(a6, Operand(Map::kSlackTrackingCounterEnd - 1));
427 425
428 __ bind(&allocate); 426 __ bind(&allocate);
429 } 427 }
430 428
431 // Now allocate the JSObject on the heap. 429 // Now allocate the JSObject on the heap.
432 // a1: constructor function 430 // a1: constructor function
433 // a2: initial map 431 // a2: initial map
434 Label rt_call_reload_new_target; 432 // a6: slack tracking counter (non-API function case)
435 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); 433 __ lbu(a4, FieldMemOperand(a2, Map::kInstanceSizeOffset));
436 434 __ Allocate(a4, t0, a4, t2, &rt_call, SIZE_IN_WORDS);
437 __ Allocate(a3, t0, a4, t2, &rt_call_reload_new_target, SIZE_IN_WORDS);
438 435
439 // Allocated the JSObject, now initialize the fields. Map is set to 436 // Allocated the JSObject, now initialize the fields. Map is set to
440 // initial map and properties and elements are set to empty fixed array. 437 // initial map and properties and elements are set to empty fixed array.
441 // a1: constructor function 438 // a1: constructor function
442 // a2: initial map 439 // a2: initial map
443 // a3: object size 440 // a3: object size
444 // t0: JSObject (not tagged) 441 // t0: JSObject (not tagged)
445 // a4: start of next object 442 // a4: start of next object
443 // a6: slack tracking counter (non-API function case)
446 __ LoadRoot(t2, Heap::kEmptyFixedArrayRootIndex); 444 __ LoadRoot(t2, Heap::kEmptyFixedArrayRootIndex);
447 __ mov(t1, t0); 445 __ mov(t1, t0);
448 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset); 446 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset);
449 __ sd(a2, MemOperand(t1, JSObject::kMapOffset)); 447 __ sd(a2, MemOperand(t1, JSObject::kMapOffset));
450 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset); 448 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset);
451 __ sd(t2, MemOperand(t1, JSObject::kPropertiesOffset)); 449 __ sd(t2, MemOperand(t1, JSObject::kPropertiesOffset));
452 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset); 450 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset);
453 __ sd(t2, MemOperand(t1, JSObject::kElementsOffset)); 451 __ sd(t2, MemOperand(t1, JSObject::kElementsOffset));
452 STATIC_ASSERT(3 * kPointerSize == JSObject::kHeaderSize);
454 __ Daddu(t1, t1, Operand(3 * kPointerSize)); 453 __ Daddu(t1, t1, Operand(3 * kPointerSize));
455 454
456 // Fill all the in-object properties with appropriate filler. 455 // Fill all the in-object properties with appropriate filler.
457 // a1: constructor function
458 // a2: initial map
459 // a3: object size (in words)
460 // t0: JSObject (not tagged)
461 // a4: start of next object
462 // t1: First in-object property of JSObject (not tagged) 456 // t1: First in-object property of JSObject (not tagged)
463 // a6: slack tracking counter (non-API function case)
464 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
465 457
466 // Use t3 to hold undefined, which is used in several places below. 458 // Use t3 to hold undefined, which is used in several places below.
467 __ LoadRoot(t3, Heap::kUndefinedValueRootIndex); 459 __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
468 460
469 if (!is_api_function) { 461 if (!is_api_function) {
470 Label no_inobject_slack_tracking; 462 Label no_inobject_slack_tracking;
471 463
472 // Check if slack tracking is enabled. 464 // Check if slack tracking is enabled.
473 __ Branch( 465 __ Branch(
474 &no_inobject_slack_tracking, lt, a6, 466 &no_inobject_slack_tracking, lt, a6,
475 Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd))); 467 Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
476 468
477 // Allocate object with a slack. 469 // Allocate object with a slack.
478 __ lbu(a0, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset)); 470 __ lbu(a0, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
479 __ dsll(a0, a0, kPointerSizeLog2); 471 __ dsll(a0, a0, kPointerSizeLog2);
480 __ dsubu(a0, a4, a0); 472 __ dsubu(a0, a4, a0);
481 // a0: offset of first field after pre-allocated fields 473 // a0: offset of first field after pre-allocated fields
482 if (FLAG_debug_code) { 474 if (FLAG_debug_code) {
483 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields, t1, 475 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields, t1,
484 Operand(a0)); 476 Operand(a0));
485 } 477 }
486 __ InitializeFieldsWithFiller(t1, a0, t3); 478 __ InitializeFieldsWithFiller(t1, a0, t3);
487 // To allow for truncation. 479
480 // To allow truncation fill the remaining fields with one pointer
481 // filler map.
488 __ LoadRoot(t3, Heap::kOnePointerFillerMapRootIndex); 482 __ LoadRoot(t3, Heap::kOnePointerFillerMapRootIndex);
489 // Fill the remaining fields with one pointer filler map.
490 483
491 __ bind(&no_inobject_slack_tracking); 484 __ bind(&no_inobject_slack_tracking);
492 } 485 }
493 486
494 __ InitializeFieldsWithFiller(t1, a4, t3); 487 __ InitializeFieldsWithFiller(t1, a4, t3);
495 488
496 // Add the object tag to make the JSObject real, so that we can continue 489 // 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. 490 // and jump into the continuation code at any time from now on.
498 __ Daddu(t0, t0, Operand(kHeapObjectTag)); 491 __ Daddu(t0, t0, Operand(kHeapObjectTag));
499 492
500 // Continue with JSObject being successfully allocated. 493 // Continue with JSObject being successfully allocated.
494 // a1: constructor function
495 // a3: new target
501 // a4: JSObject 496 // a4: JSObject
502 __ jmp(&allocated); 497 __ jmp(&allocated);
503
504 // Reload the new target and fall-through.
505 __ bind(&rt_call_reload_new_target);
506 __ ld(a3, MemOperand(sp, 0 * kPointerSize));
507 } 498 }
508 499
509 // Allocate the new receiver object using the runtime call. 500 // Allocate the new receiver object using the runtime call.
510 // a1: constructor function 501 // a1: constructor function
511 // a3: new target 502 // a3: new target
512 __ bind(&rt_call); 503 __ bind(&rt_call);
513 504
514 __ Push(a1, a3); // constructor function, new target 505 // Push the constructor and new_target twice, second pair as arguments
506 // to the runtime call.
507 __ Push(a1, a3, a1, a3); // constructor function, new target
515 __ CallRuntime(Runtime::kNewObject, 2); 508 __ CallRuntime(Runtime::kNewObject, 2);
516 __ mov(t0, v0); 509 __ mov(t0, v0);
510 __ Pop(a1, a3);
517 511
518 // Receiver for constructor call allocated. 512 // Receiver for constructor call allocated.
513 // a1: constructor function
514 // a3: new target
519 // t0: JSObject 515 // t0: JSObject
520 __ bind(&allocated); 516 __ bind(&allocated);
521 517
522 // Restore the parameters.
523 __ Pop(a3); // new.target
524 __ Pop(a1);
525
526 __ ld(a0, MemOperand(sp)); 518 __ ld(a0, MemOperand(sp));
527 } 519 }
528 __ SmiUntag(a0); 520 __ SmiUntag(a0);
529 521
530 // Push new.target onto the construct frame. This is stored just below the 522 // Push new.target onto the construct frame. This is stored just below the
531 // receiver on the stack. 523 // receiver on the stack.
532 if (create_implicit_receiver) { 524 if (create_implicit_receiver) {
533 // Push the allocated receiver to the stack. We need two copies 525 // Push the allocated receiver to the stack. We need two copies
534 // because we may have to return the original one and the calling 526 // because we may have to return the original one and the calling
535 // conventions dictate that the called function pops the receiver. 527 // conventions dictate that the called function pops the receiver.
(...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after
1868 } 1860 }
1869 } 1861 }
1870 1862
1871 1863
1872 #undef __ 1864 #undef __
1873 1865
1874 } // namespace internal 1866 } // namespace internal
1875 } // namespace v8 1867 } // namespace v8
1876 1868
1877 #endif // V8_TARGET_ARCH_MIPS64 1869 #endif // V8_TARGET_ARCH_MIPS64
OLDNEW
« no previous file with comments | « src/mips/macro-assembler-mips.cc ('k') | src/mips64/code-stubs-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698