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

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

Issue 295933012: Revert "Inobject slack tracking is done on a per-closure basis instead of per-shared info basis." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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 | Annotate | Revision Log
« no previous file with comments | « src/arm/macro-assembler-arm.h ('k') | src/arm64/macro-assembler-arm64.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 #include "v8.h" 5 #include "v8.h"
6 6
7 #if V8_TARGET_ARCH_ARM64 7 #if V8_TARGET_ARCH_ARM64
8 8
9 #include "codegen.h" 9 #include "codegen.h"
10 #include "debug.h" 10 #include "debug.h"
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 CallRuntimePassFunction(masm, Runtime::kHiddenTryInstallOptimizedCode); 297 CallRuntimePassFunction(masm, Runtime::kHiddenTryInstallOptimizedCode);
298 GenerateTailCallToReturnedCode(masm); 298 GenerateTailCallToReturnedCode(masm);
299 299
300 __ Bind(&ok); 300 __ Bind(&ok);
301 GenerateTailCallToSharedCode(masm); 301 GenerateTailCallToSharedCode(masm);
302 } 302 }
303 303
304 304
305 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 305 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
306 bool is_api_function, 306 bool is_api_function,
307 bool count_constructions,
307 bool create_memento) { 308 bool create_memento) {
308 // ----------- S t a t e ------------- 309 // ----------- S t a t e -------------
309 // -- x0 : number of arguments 310 // -- x0 : number of arguments
310 // -- x1 : constructor function 311 // -- x1 : constructor function
311 // -- x2 : allocation site or undefined 312 // -- x2 : allocation site or undefined
312 // -- lr : return address 313 // -- lr : return address
313 // -- sp[...]: constructor arguments 314 // -- sp[...]: constructor arguments
314 // ----------------------------------- 315 // -----------------------------------
315 316
316 ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); 317 ASM_LOCATION("Builtins::Generate_JSConstructStubHelper");
318 // Should never count constructions for api objects.
319 ASSERT(!is_api_function || !count_constructions);
317 // Should never create mementos for api functions. 320 // Should never create mementos for api functions.
318 ASSERT(!is_api_function || !create_memento); 321 ASSERT(!is_api_function || !create_memento);
322 // Should never create mementos before slack tracking is finished.
323 ASSERT(!count_constructions || !create_memento);
319 324
320 Isolate* isolate = masm->isolate(); 325 Isolate* isolate = masm->isolate();
321 326
322 // Enter a construct frame. 327 // Enter a construct frame.
323 { 328 {
324 FrameScope scope(masm, StackFrame::CONSTRUCT); 329 FrameScope scope(masm, StackFrame::CONSTRUCT);
325 330
326 // Preserve the three incoming parameters on the stack. 331 // Preserve the three incoming parameters on the stack.
327 if (create_memento) { 332 if (create_memento) {
328 __ AssertUndefinedOrAllocationSite(x2, x10); 333 __ AssertUndefinedOrAllocationSite(x2, x10);
(...skipping 25 matching lines...) Expand all
354 JSFunction::kPrototypeOrInitialMapOffset)); 359 JSFunction::kPrototypeOrInitialMapOffset));
355 __ JumpIfSmi(init_map, &rt_call); 360 __ JumpIfSmi(init_map, &rt_call);
356 __ JumpIfNotObjectType(init_map, x10, x11, MAP_TYPE, &rt_call); 361 __ JumpIfNotObjectType(init_map, x10, x11, MAP_TYPE, &rt_call);
357 362
358 // Check that the constructor is not constructing a JSFunction (see 363 // Check that the constructor is not constructing a JSFunction (see
359 // comments in Runtime_NewObject in runtime.cc). In which case the initial 364 // comments in Runtime_NewObject in runtime.cc). In which case the initial
360 // map's instance type would be JS_FUNCTION_TYPE. 365 // map's instance type would be JS_FUNCTION_TYPE.
361 __ CompareInstanceType(init_map, x10, JS_FUNCTION_TYPE); 366 __ CompareInstanceType(init_map, x10, JS_FUNCTION_TYPE);
362 __ B(eq, &rt_call); 367 __ B(eq, &rt_call);
363 368
364 Register constructon_count = x14; 369 if (count_constructions) {
365 if (!is_api_function) {
366 Label allocate; 370 Label allocate;
367 MemOperand bit_field3 =
368 FieldMemOperand(init_map, Map::kBitField3Offset);
369 // Check if slack tracking is enabled.
370 __ Ldr(x4, bit_field3);
371 __ DecodeField<Map::ConstructionCount>(constructon_count, x4);
372 __ Cmp(constructon_count, Operand(JSFunction::kNoSlackTracking));
373 __ B(eq, &allocate);
374 // Decrease generous allocation count. 371 // Decrease generous allocation count.
375 __ Subs(x4, x4, Operand(1 << Map::ConstructionCount::kShift)); 372 __ Ldr(x3, FieldMemOperand(constructor,
376 __ Str(x4, bit_field3); 373 JSFunction::kSharedFunctionInfoOffset));
377 __ Cmp(constructon_count, Operand(JSFunction::kFinishSlackTracking)); 374 MemOperand constructor_count =
375 FieldMemOperand(x3, SharedFunctionInfo::kConstructionCountOffset);
376 __ Ldrb(x4, constructor_count);
377 __ Subs(x4, x4, 1);
378 __ Strb(x4, constructor_count);
378 __ B(ne, &allocate); 379 __ B(ne, &allocate);
379 380
380 // Push the constructor and map to the stack, and the constructor again 381 // Push the constructor and map to the stack, and the constructor again
381 // as argument to the runtime call. 382 // as argument to the runtime call.
382 __ Push(constructor, init_map, constructor); 383 __ Push(constructor, init_map, constructor);
384 // The call will replace the stub, so the countdown is only done once.
383 __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1); 385 __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1);
384 __ Pop(init_map, constructor); 386 __ Pop(init_map, constructor);
385 __ Mov(constructon_count, Operand(JSFunction::kNoSlackTracking));
386 __ Bind(&allocate); 387 __ Bind(&allocate);
387 } 388 }
388 389
389 // Now allocate the JSObject on the heap. 390 // Now allocate the JSObject on the heap.
390 Register obj_size = x3; 391 Register obj_size = x3;
391 Register new_obj = x4; 392 Register new_obj = x4;
392 __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset)); 393 __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset));
393 if (create_memento) { 394 if (create_memento) {
394 __ Add(x7, obj_size, 395 __ Add(x7, obj_size,
395 Operand(AllocationMemento::kSize / kPointerSize)); 396 Operand(AllocationMemento::kSize / kPointerSize));
396 __ Allocate(x7, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); 397 __ Allocate(x7, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS);
397 } else { 398 } else {
398 __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); 399 __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS);
399 } 400 }
400 401
401 // Allocated the JSObject, now initialize the fields. Map is set to 402 // Allocated the JSObject, now initialize the fields. Map is set to
402 // initial map and properties and elements are set to empty fixed array. 403 // initial map and properties and elements are set to empty fixed array.
403 // NB. the object pointer is not tagged, so MemOperand is used. 404 // NB. the object pointer is not tagged, so MemOperand is used.
404 Register empty = x5; 405 Register empty = x5;
405 __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); 406 __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex);
406 __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset)); 407 __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset));
407 STATIC_ASSERT(JSObject::kElementsOffset == 408 STATIC_ASSERT(JSObject::kElementsOffset ==
408 (JSObject::kPropertiesOffset + kPointerSize)); 409 (JSObject::kPropertiesOffset + kPointerSize));
409 __ Stp(empty, empty, MemOperand(new_obj, JSObject::kPropertiesOffset)); 410 __ Stp(empty, empty, MemOperand(new_obj, JSObject::kPropertiesOffset));
410 411
411 Register first_prop = x5; 412 Register first_prop = x5;
412 __ Add(first_prop, new_obj, JSObject::kHeaderSize); 413 __ Add(first_prop, new_obj, JSObject::kHeaderSize);
413 414
414 // Fill all of the in-object properties with the appropriate filler. 415 // Fill all of the in-object properties with the appropriate filler.
415 Register filler = x7; 416 Register undef = x7;
416 __ LoadRoot(filler, Heap::kUndefinedValueRootIndex); 417 __ LoadRoot(undef, Heap::kUndefinedValueRootIndex);
417 418
418 // Obtain number of pre-allocated property fields and in-object 419 // Obtain number of pre-allocated property fields and in-object
419 // properties. 420 // properties.
420 Register prealloc_fields = x10; 421 Register prealloc_fields = x10;
421 Register inobject_props = x11; 422 Register inobject_props = x11;
422 Register inst_sizes = x11; 423 Register inst_sizes = x11;
423 __ Ldr(inst_sizes, FieldMemOperand(init_map, Map::kInstanceSizesOffset)); 424 __ Ldr(inst_sizes, FieldMemOperand(init_map, Map::kInstanceSizesOffset));
424 __ Ubfx(prealloc_fields, inst_sizes, 425 __ Ubfx(prealloc_fields, inst_sizes,
425 Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 426 Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
426 kBitsPerByte); 427 kBitsPerByte);
427 __ Ubfx(inobject_props, inst_sizes, 428 __ Ubfx(inobject_props, inst_sizes,
428 Map::kInObjectPropertiesByte * kBitsPerByte, kBitsPerByte); 429 Map::kInObjectPropertiesByte * kBitsPerByte, kBitsPerByte);
429 430
430 // Calculate number of property fields in the object. 431 // Calculate number of property fields in the object.
431 Register prop_fields = x6; 432 Register prop_fields = x6;
432 __ Sub(prop_fields, obj_size, JSObject::kHeaderSize / kPointerSize); 433 __ Sub(prop_fields, obj_size, JSObject::kHeaderSize / kPointerSize);
433 434
434 if (!is_api_function) { 435 if (count_constructions) {
435 Label no_inobject_slack_tracking; 436 // Fill the pre-allocated fields with undef.
437 __ FillFields(first_prop, prealloc_fields, undef);
436 438
437 // Check if slack tracking is enabled. 439 // Register first_non_prealloc is the offset of the first field after
438 __ Cmp(constructon_count, Operand(JSFunction::kNoSlackTracking));
439 __ B(eq, &no_inobject_slack_tracking);
440 constructon_count = NoReg;
441
442 // Fill the pre-allocated fields with undef.
443 __ FillFields(first_prop, prealloc_fields, filler);
444
445 // Update first_prop register to be the offset of the first field after
446 // pre-allocated fields. 440 // pre-allocated fields.
447 __ Add(first_prop, first_prop, 441 Register first_non_prealloc = x12;
442 __ Add(first_non_prealloc, first_prop,
448 Operand(prealloc_fields, LSL, kPointerSizeLog2)); 443 Operand(prealloc_fields, LSL, kPointerSizeLog2));
449 444
445 first_prop = NoReg;
446
450 if (FLAG_debug_code) { 447 if (FLAG_debug_code) {
451 Register obj_end = x14; 448 Register obj_end = x5;
452 __ Add(obj_end, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); 449 __ Add(obj_end, new_obj, Operand(obj_size, LSL, kPointerSizeLog2));
453 __ Cmp(first_prop, obj_end); 450 __ Cmp(first_non_prealloc, obj_end);
454 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); 451 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
455 } 452 }
456 453
457 // Fill the remaining fields with one pointer filler map. 454 // Fill the remaining fields with one pointer filler map.
458 __ LoadRoot(filler, Heap::kOnePointerFillerMapRootIndex); 455 Register one_pointer_filler = x5;
459 __ Sub(prop_fields, prop_fields, prealloc_fields); 456 Register non_prealloc_fields = x6;
460 457 __ LoadRoot(one_pointer_filler, Heap::kOnePointerFillerMapRootIndex);
461 __ bind(&no_inobject_slack_tracking); 458 __ Sub(non_prealloc_fields, prop_fields, prealloc_fields);
462 } 459 __ FillFields(first_non_prealloc, non_prealloc_fields,
463 if (create_memento) { 460 one_pointer_filler);
461 prop_fields = NoReg;
462 } else if (create_memento) {
464 // Fill the pre-allocated fields with undef. 463 // Fill the pre-allocated fields with undef.
465 __ FillFields(first_prop, prop_fields, filler); 464 __ FillFields(first_prop, prop_fields, undef);
466 __ Add(first_prop, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); 465 __ Add(first_prop, new_obj, Operand(obj_size, LSL, kPointerSizeLog2));
467 __ LoadRoot(x14, Heap::kAllocationMementoMapRootIndex); 466 __ LoadRoot(x14, Heap::kAllocationMementoMapRootIndex);
468 ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset); 467 ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset);
469 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); 468 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex));
470 // Load the AllocationSite 469 // Load the AllocationSite
471 __ Peek(x14, 2 * kXRegSize); 470 __ Peek(x14, 2 * kXRegSize);
472 ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); 471 ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset);
473 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); 472 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex));
474 first_prop = NoReg; 473 first_prop = NoReg;
475 } else { 474 } else {
476 // Fill all of the property fields with undef. 475 // Fill all of the property fields with undef.
477 __ FillFields(first_prop, prop_fields, filler); 476 __ FillFields(first_prop, prop_fields, undef);
478 first_prop = NoReg; 477 first_prop = NoReg;
479 prop_fields = NoReg; 478 prop_fields = NoReg;
480 } 479 }
481 480
482 // Add the object tag to make the JSObject real, so that we can continue 481 // Add the object tag to make the JSObject real, so that we can continue
483 // and jump into the continuation code at any time from now on. Any 482 // and jump into the continuation code at any time from now on. Any
484 // failures need to undo the allocation, so that the heap is in a 483 // failures need to undo the allocation, so that the heap is in a
485 // consistent state and verifiable. 484 // consistent state and verifiable.
486 __ Add(new_obj, new_obj, kHeapObjectTag); 485 __ Add(new_obj, new_obj, kHeapObjectTag);
487 486
(...skipping 22 matching lines...) Expand all
510 509
511 Register array_map = x10; 510 Register array_map = x10;
512 __ LoadRoot(array_map, Heap::kFixedArrayMapRootIndex); 511 __ LoadRoot(array_map, Heap::kFixedArrayMapRootIndex);
513 __ Str(array_map, MemOperand(new_array, FixedArray::kMapOffset)); 512 __ Str(array_map, MemOperand(new_array, FixedArray::kMapOffset));
514 __ SmiTag(x0, element_count); 513 __ SmiTag(x0, element_count);
515 __ Str(x0, MemOperand(new_array, FixedArray::kLengthOffset)); 514 __ Str(x0, MemOperand(new_array, FixedArray::kLengthOffset));
516 515
517 // Initialize the fields to undefined. 516 // Initialize the fields to undefined.
518 Register elements = x10; 517 Register elements = x10;
519 __ Add(elements, new_array, FixedArray::kHeaderSize); 518 __ Add(elements, new_array, FixedArray::kHeaderSize);
520 __ FillFields(elements, element_count, filler); 519 __ FillFields(elements, element_count, undef);
521 520
522 // Store the initialized FixedArray into the properties field of the 521 // Store the initialized FixedArray into the properties field of the
523 // JSObject. 522 // JSObject.
524 __ Add(new_array, new_array, kHeapObjectTag); 523 __ Add(new_array, new_array, kHeapObjectTag);
525 __ Str(new_array, FieldMemOperand(new_obj, JSObject::kPropertiesOffset)); 524 __ Str(new_array, FieldMemOperand(new_obj, JSObject::kPropertiesOffset));
526 525
527 // Continue with JSObject being successfully allocated. 526 // Continue with JSObject being successfully allocated.
528 __ B(&allocated); 527 __ B(&allocated);
529 528
530 // Undo the setting of the new top so that the heap is verifiable. For 529 // Undo the setting of the new top so that the heap is verifiable. For
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); 617 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset));
619 Handle<Code> code = 618 Handle<Code> code =
620 masm->isolate()->builtins()->HandleApiCallConstruct(); 619 masm->isolate()->builtins()->HandleApiCallConstruct();
621 __ Call(code, RelocInfo::CODE_TARGET); 620 __ Call(code, RelocInfo::CODE_TARGET);
622 } else { 621 } else {
623 ParameterCount actual(argc); 622 ParameterCount actual(argc);
624 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); 623 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper());
625 } 624 }
626 625
627 // Store offset of return address for deoptimizer. 626 // Store offset of return address for deoptimizer.
628 if (!is_api_function) { 627 if (!is_api_function && !count_constructions) {
629 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 628 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
630 } 629 }
631 630
632 // Restore the context from the frame. 631 // Restore the context from the frame.
633 // x0: result 632 // x0: result
634 // jssp[0]: receiver 633 // jssp[0]: receiver
635 // jssp[1]: constructor function 634 // jssp[1]: constructor function
636 // jssp[2]: number of arguments (smi-tagged) 635 // jssp[2]: number of arguments (smi-tagged)
637 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 636 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
638 637
(...skipping 30 matching lines...) Expand all
669 // Leave construct frame. 668 // Leave construct frame.
670 } 669 }
671 670
672 __ DropBySMI(x1); 671 __ DropBySMI(x1);
673 __ Drop(1); 672 __ Drop(1);
674 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); 673 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2);
675 __ Ret(); 674 __ Ret();
676 } 675 }
677 676
678 677
678 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
679 Generate_JSConstructStubHelper(masm, false, true, false);
680 }
681
682
679 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 683 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
680 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); 684 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new);
681 } 685 }
682 686
683 687
684 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 688 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
685 Generate_JSConstructStubHelper(masm, true, false); 689 Generate_JSConstructStubHelper(masm, true, false, false);
686 } 690 }
687 691
688 692
689 // Input: 693 // Input:
690 // x0: code entry. 694 // x0: code entry.
691 // x1: function. 695 // x1: function.
692 // x2: receiver. 696 // x2: receiver.
693 // x3: argc. 697 // x3: argc.
694 // x4: argv. 698 // x4: argv.
695 // Output: 699 // Output:
(...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 __ Unreachable(); 1560 __ Unreachable();
1557 } 1561 }
1558 } 1562 }
1559 1563
1560 1564
1561 #undef __ 1565 #undef __
1562 1566
1563 } } // namespace v8::internal 1567 } } // namespace v8::internal
1564 1568
1565 #endif // V8_TARGET_ARCH_ARM 1569 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/macro-assembler-arm.h ('k') | src/arm64/macro-assembler-arm64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698