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

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

Issue 294973013: MIPS: Reland r21442 "Inobject slack tracking is done on a per-closure basis instead of per-shared i… (Closed) Base URL: https://github.com/v8/v8.git@gbl
Patch Set: Fix #2 Created 6 years, 7 months 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 | src/mips/macro-assembler-mips.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 5
6 6
7 #include "v8.h" 7 #include "v8.h"
8 8
9 #if V8_TARGET_ARCH_MIPS 9 #if V8_TARGET_ARCH_MIPS
10 10
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 CallRuntimePassFunction(masm, Runtime::kHiddenTryInstallOptimizedCode); 312 CallRuntimePassFunction(masm, Runtime::kHiddenTryInstallOptimizedCode);
313 GenerateTailCallToReturnedCode(masm); 313 GenerateTailCallToReturnedCode(masm);
314 314
315 __ bind(&ok); 315 __ bind(&ok);
316 GenerateTailCallToSharedCode(masm); 316 GenerateTailCallToSharedCode(masm);
317 } 317 }
318 318
319 319
320 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 320 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
321 bool is_api_function, 321 bool is_api_function,
322 bool count_constructions,
323 bool create_memento) { 322 bool create_memento) {
324 // ----------- S t a t e ------------- 323 // ----------- S t a t e -------------
325 // -- a0 : number of arguments 324 // -- a0 : number of arguments
326 // -- a1 : constructor function 325 // -- a1 : constructor function
327 // -- a2 : allocation site or undefined 326 // -- a2 : allocation site or undefined
328 // -- ra : return address 327 // -- ra : return address
329 // -- sp[...]: constructor arguments 328 // -- sp[...]: constructor arguments
330 // ----------------------------------- 329 // -----------------------------------
331 330
332 // Should never count constructions for api objects.
333 ASSERT(!is_api_function || !count_constructions);
334
335 // Should never create mementos for api functions. 331 // Should never create mementos for api functions.
336 ASSERT(!is_api_function || !create_memento); 332 ASSERT(!is_api_function || !create_memento);
337 333
338 // Should never create mementos before slack tracking is finished.
339 ASSERT(!count_constructions || !create_memento);
340
341 Isolate* isolate = masm->isolate(); 334 Isolate* isolate = masm->isolate();
342 335
343 // ----------- S t a t e ------------- 336 // ----------- S t a t e -------------
344 // -- a0 : number of arguments 337 // -- a0 : number of arguments
345 // -- a1 : constructor function 338 // -- a1 : constructor function
346 // -- ra : return address 339 // -- ra : return address
347 // -- sp[...]: constructor arguments 340 // -- sp[...]: constructor arguments
348 // ----------------------------------- 341 // -----------------------------------
349 342
350 // Enter a construct frame. 343 // Enter a construct frame.
351 { 344 {
352 FrameScope scope(masm, StackFrame::CONSTRUCT); 345 FrameScope scope(masm, StackFrame::CONSTRUCT);
353 346
354 if (create_memento) { 347 if (create_memento) {
355 __ AssertUndefinedOrAllocationSite(a2, a3); 348 __ AssertUndefinedOrAllocationSite(a2, a3);
356 __ push(a2); 349 __ push(a2);
357 } 350 }
358 351
359 // Preserve the two incoming parameters on the stack. 352 // Preserve the two incoming parameters on the stack.
360 __ sll(a0, a0, kSmiTagSize); // Tag arguments count. 353 __ sll(a0, a0, kSmiTagSize); // Tag arguments count.
361 __ MultiPushReversed(a0.bit() | a1.bit()); 354 __ MultiPushReversed(a0.bit() | a1.bit());
362 355
363 // Use t7 to hold undefined, which is used in several places below.
364 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
365
366 Label rt_call, allocated; 356 Label rt_call, allocated;
367 // Try to allocate the object without transitioning into C code. If any of 357 // Try to allocate the object without transitioning into C code. If any of
368 // the preconditions is not met, the code bails out to the runtime call. 358 // the preconditions is not met, the code bails out to the runtime call.
369 if (FLAG_inline_new) { 359 if (FLAG_inline_new) {
370 Label undo_allocation; 360 Label undo_allocation;
371 ExternalReference debug_step_in_fp = 361 ExternalReference debug_step_in_fp =
372 ExternalReference::debug_step_in_fp_address(isolate); 362 ExternalReference::debug_step_in_fp_address(isolate);
373 __ li(a2, Operand(debug_step_in_fp)); 363 __ li(a2, Operand(debug_step_in_fp));
374 __ lw(a2, MemOperand(a2)); 364 __ lw(a2, MemOperand(a2));
375 __ Branch(&rt_call, ne, a2, Operand(zero_reg)); 365 __ Branch(&rt_call, ne, a2, Operand(zero_reg));
376 366
377 // Load the initial map and verify that it is in fact a map. 367 // Load the initial map and verify that it is in fact a map.
378 // a1: constructor function 368 // a1: constructor function
379 __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); 369 __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
380 __ JumpIfSmi(a2, &rt_call); 370 __ JumpIfSmi(a2, &rt_call);
381 __ GetObjectType(a2, a3, t4); 371 __ GetObjectType(a2, a3, t4);
382 __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE)); 372 __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE));
383 373
384 // Check that the constructor is not constructing a JSFunction (see 374 // Check that the constructor is not constructing a JSFunction (see
385 // comments in Runtime_NewObject in runtime.cc). In which case the 375 // comments in Runtime_NewObject in runtime.cc). In which case the
386 // initial map's instance type would be JS_FUNCTION_TYPE. 376 // initial map's instance type would be JS_FUNCTION_TYPE.
387 // a1: constructor function 377 // a1: constructor function
388 // a2: initial map 378 // a2: initial map
389 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset)); 379 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
390 __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE)); 380 __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
391 381
392 if (count_constructions) { 382 // Use t7 to hold undefined, which is used in several places below.
383 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
384
385 if (!is_api_function) {
393 Label allocate; 386 Label allocate;
387 MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset);
388 // Check if slack tracking is enabled.
389 __ lw(t0, bit_field3);
390 __ DecodeField<Map::ConstructionCount>(t2, t0);
391 __ Branch(&allocate, eq, t2, Operand(JSFunction::kNoSlackTracking));
394 // Decrease generous allocation count. 392 // Decrease generous allocation count.
395 __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 393 __ Subu(t0, t0, Operand(1 << Map::ConstructionCount::kShift));
396 MemOperand constructor_count = 394 __ Branch(USE_DELAY_SLOT,
397 FieldMemOperand(a3, SharedFunctionInfo::kConstructionCountOffset); 395 &allocate, ne, t2, Operand(JSFunction::kFinishSlackTracking));
398 __ lbu(t0, constructor_count); 396 __ sw(t0, bit_field3); // In delay slot.
399 __ Subu(t0, t0, Operand(1));
400 __ sb(t0, constructor_count);
401 __ Branch(&allocate, ne, t0, Operand(zero_reg));
402 397
403 __ Push(a1, a2, a1); // a1 = Constructor. 398 __ Push(a1, a2, a1); // a1 = Constructor.
404 // The call will replace the stub, so the countdown is only done once.
405 __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1); 399 __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1);
406 400
407 __ Pop(a1, a2); 401 __ Pop(a1, a2);
Igor Sheludko 2014/05/23 18:10:19 t2 must be set to zero here (which is JSFunction::
408 402
409 __ bind(&allocate); 403 __ bind(&allocate);
410 } 404 }
411 405
412 // Now allocate the JSObject on the heap. 406 // Now allocate the JSObject on the heap.
413 // a1: constructor function 407 // a1: constructor function
414 // a2: initial map 408 // a2: initial map
415 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); 409 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
416 if (create_memento) { 410 if (create_memento) {
417 __ Addu(a3, a3, Operand(AllocationMemento::kSize / kPointerSize)); 411 __ Addu(a3, a3, Operand(AllocationMemento::kSize / kPointerSize));
(...skipping 16 matching lines...) Expand all
434 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 428 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
435 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 429 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
436 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 430 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
437 431
438 // Fill all the in-object properties with appropriate filler. 432 // Fill all the in-object properties with appropriate filler.
439 // a1: constructor function 433 // a1: constructor function
440 // a2: initial map 434 // a2: initial map
441 // a3: object size (in words, including memento if create_memento) 435 // a3: object size (in words, including memento if create_memento)
442 // t4: JSObject (not tagged) 436 // t4: JSObject (not tagged)
443 // t5: First in-object property of JSObject (not tagged) 437 // t5: First in-object property of JSObject (not tagged)
438 // t2: slack tracking counter (non-API function case)
444 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); 439 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
445 440
Igor Sheludko 2014/05/23 18:10:19 I think t7 initialization should be moved here:
446 if (count_constructions) { 441 if (!is_api_function) {
447 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); 442 Label no_inobject_slack_tracking;
443
444 // Check if slack tracking is enabled.
445 __ Branch(&no_inobject_slack_tracking,
446 eq, t2, Operand(JSFunction::kNoSlackTracking));
447
448 // Allocate object with a slack.
448 __ lbu(a0, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset)); 449 __ lbu(a0, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
449 __ sll(at, a0, kPointerSizeLog2); 450 __ sll(at, a0, kPointerSizeLog2);
450 __ addu(a0, t5, at); 451 __ addu(a0, t5, at);
451 __ sll(at, a3, kPointerSizeLog2);
452 __ Addu(t6, t4, Operand(at)); // End of object.
453 // a0: offset of first field after pre-allocated fields 452 // a0: offset of first field after pre-allocated fields
454 if (FLAG_debug_code) { 453 if (FLAG_debug_code) {
454 __ sll(at, a3, kPointerSizeLog2);
455 __ Addu(t6, t4, Operand(at)); // End of object.
455 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields, 456 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields,
456 a0, Operand(t6)); 457 a0, Operand(t6));
457 } 458 }
458 __ InitializeFieldsWithFiller(t5, a0, t7); 459 __ InitializeFieldsWithFiller(t5, a0, t7);
459 // To allow for truncation. 460 // To allow for truncation.
460 __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex); 461 __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex);
461 __ InitializeFieldsWithFiller(t5, t6, t7); 462 // Fill the remaining fields with one pointer filler map.
462 } else if (create_memento) { 463
463 __ Subu(t7, a3, Operand(AllocationMemento::kSize / kPointerSize)); 464 __ bind(&no_inobject_slack_tracking);
464 __ sll(at, t7, kPointerSizeLog2); 465 }
465 __ Addu(a0, t4, Operand(at)); // End of object. 466
466 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); 467 if (create_memento) {
468 __ Subu(a0, a3, Operand(AllocationMemento::kSize / kPointerSize));
469 __ sll(a0, a0, kPointerSizeLog2);
470 __ Addu(a0, t4, Operand(a0)); // End of object.
467 __ InitializeFieldsWithFiller(t5, a0, t7); 471 __ InitializeFieldsWithFiller(t5, a0, t7);
468 472
469 // Fill in memento fields. 473 // Fill in memento fields.
470 // t5: points to the allocated but uninitialized memento. 474 // t5: points to the allocated but uninitialized memento.
471 __ LoadRoot(t7, Heap::kAllocationMementoMapRootIndex); 475 __ LoadRoot(t7, Heap::kAllocationMementoMapRootIndex);
472 ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset); 476 ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset);
473 __ sw(t7, MemOperand(t5)); 477 __ sw(t7, MemOperand(t5));
474 __ Addu(t5, t5, kPointerSize); 478 __ Addu(t5, t5, kPointerSize);
475 // Load the AllocationSite. 479 // Load the AllocationSite.
476 __ lw(t7, MemOperand(sp, 2 * kPointerSize)); 480 __ lw(t7, MemOperand(sp, 2 * kPointerSize));
477 ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); 481 ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset);
478 __ sw(t7, MemOperand(t5)); 482 __ sw(t7, MemOperand(t5));
479 __ Addu(t5, t5, kPointerSize); 483 __ Addu(t5, t5, kPointerSize);
480 } else { 484 } else {
481 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
482 __ sll(at, a3, kPointerSizeLog2); 485 __ sll(at, a3, kPointerSizeLog2);
483 __ Addu(a0, t4, Operand(at)); // End of object. 486 __ Addu(a0, t4, Operand(at)); // End of object.
484 __ InitializeFieldsWithFiller(t5, a0, t7); 487 __ InitializeFieldsWithFiller(t5, a0, t7);
485 } 488 }
486 489
487 // Add the object tag to make the JSObject real, so that we can continue 490 // Add the object tag to make the JSObject real, so that we can continue
488 // and jump into the continuation code at any time from now on. Any 491 // and jump into the continuation code at any time from now on. Any
489 // failures need to undo the allocation, so that the heap is in a 492 // failures need to undo the allocation, so that the heap is in a
490 // consistent state and verifiable. 493 // consistent state and verifiable.
491 __ Addu(t4, t4, Operand(kHeapObjectTag)); 494 __ Addu(t4, t4, Operand(kHeapObjectTag));
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 // Initialize the fields to undefined. 544 // Initialize the fields to undefined.
542 // a1: constructor 545 // a1: constructor
543 // a2: First element of FixedArray (not tagged) 546 // a2: First element of FixedArray (not tagged)
544 // a3: number of elements in properties array 547 // a3: number of elements in properties array
545 // t4: JSObject 548 // t4: JSObject
546 // t5: FixedArray (not tagged) 549 // t5: FixedArray (not tagged)
547 __ sll(t3, a3, kPointerSizeLog2); 550 __ sll(t3, a3, kPointerSizeLog2);
548 __ addu(t6, a2, t3); // End of object. 551 __ addu(t6, a2, t3); // End of object.
549 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 552 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
550 { Label loop, entry; 553 { Label loop, entry;
551 if (count_constructions) { 554 if (!is_api_function || create_memento) {
552 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); 555 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
553 } else if (FLAG_debug_code) { 556 } else if (FLAG_debug_code) {
554 __ LoadRoot(t8, Heap::kUndefinedValueRootIndex); 557 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex);
555 __ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t8)); 558 __ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t2));
556 } 559 }
557 __ jmp(&entry); 560 __ jmp(&entry);
558 __ bind(&loop); 561 __ bind(&loop);
559 __ sw(t7, MemOperand(a2)); 562 __ sw(t7, MemOperand(a2));
560 __ addiu(a2, a2, kPointerSize); 563 __ addiu(a2, a2, kPointerSize);
561 __ bind(&entry); 564 __ bind(&entry);
562 __ Branch(&loop, less, a2, Operand(t6)); 565 __ Branch(&loop, less, a2, Operand(t6));
563 } 566 }
564 567
565 // Store the initialized FixedArray into the properties field of 568 // Store the initialized FixedArray into the properties field of
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 672 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
670 Handle<Code> code = 673 Handle<Code> code =
671 masm->isolate()->builtins()->HandleApiCallConstruct(); 674 masm->isolate()->builtins()->HandleApiCallConstruct();
672 __ Call(code, RelocInfo::CODE_TARGET); 675 __ Call(code, RelocInfo::CODE_TARGET);
673 } else { 676 } else {
674 ParameterCount actual(a0); 677 ParameterCount actual(a0);
675 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper()); 678 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
676 } 679 }
677 680
678 // Store offset of return address for deoptimizer. 681 // Store offset of return address for deoptimizer.
679 if (!is_api_function && !count_constructions) { 682 if (!is_api_function) {
680 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 683 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
681 } 684 }
682 685
683 // Restore context from the frame. 686 // Restore context from the frame.
684 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 687 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
685 688
686 // If the result is an object (in the ECMA sense), we should get rid 689 // If the result is an object (in the ECMA sense), we should get rid
687 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 690 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
688 // on page 74. 691 // on page 74.
689 Label use_receiver, exit; 692 Label use_receiver, exit;
(...skipping 28 matching lines...) Expand all
718 } 721 }
719 722
720 __ sll(t0, a1, kPointerSizeLog2 - 1); 723 __ sll(t0, a1, kPointerSizeLog2 - 1);
721 __ Addu(sp, sp, t0); 724 __ Addu(sp, sp, t0);
722 __ Addu(sp, sp, kPointerSize); 725 __ Addu(sp, sp, kPointerSize);
723 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2); 726 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2);
724 __ Ret(); 727 __ Ret();
725 } 728 }
726 729
727 730
728 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
729 Generate_JSConstructStubHelper(masm, false, true, false);
730 }
731
732
733 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 731 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
734 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); 732 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
735 } 733 }
736 734
737 735
738 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 736 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
739 Generate_JSConstructStubHelper(masm, true, false, false); 737 Generate_JSConstructStubHelper(masm, true, false);
740 } 738 }
741 739
742 740
743 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 741 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
744 bool is_construct) { 742 bool is_construct) {
745 // Called from JSEntryStub::GenerateBody 743 // Called from JSEntryStub::GenerateBody
746 744
747 // ----------- S t a t e ------------- 745 // ----------- S t a t e -------------
748 // -- a0: code entry 746 // -- a0: code entry
749 // -- a1: function 747 // -- a1: function
(...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after
1570 __ break_(0xCC); 1568 __ break_(0xCC);
1571 } 1569 }
1572 } 1570 }
1573 1571
1574 1572
1575 #undef __ 1573 #undef __
1576 1574
1577 } } // namespace v8::internal 1575 } } // namespace v8::internal
1578 1576
1579 #endif // V8_TARGET_ARCH_MIPS 1577 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « no previous file | src/mips/macro-assembler-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698