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

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

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