OLD | NEW |
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 Loading... |
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 Loading... |
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)); |
(...skipping 28 matching lines...) Expand all Loading... |
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 // Fill all of the property fields with undef. |
| 436 __ FillFields(first_prop, prop_fields, undef); |
| 437 first_prop = NoReg; |
| 438 prop_fields = NoReg; |
| 439 } else { |
| 440 Label no_inobject_slack_tracking, done_field_initialization; |
| 441 |
| 442 // Check if slack tracking is enabled. |
| 443 __ Cmp(constructon_count, Operand(JSFunction::kNoSlackTracking)); |
| 444 __ B(eq, &no_inobject_slack_tracking); |
| 445 constructon_count = NoReg; |
| 446 |
436 // Fill the pre-allocated fields with undef. | 447 // Fill the pre-allocated fields with undef. |
437 __ FillFields(first_prop, prealloc_fields, undef); | 448 __ FillFields(first_prop, prealloc_fields, undef); |
438 | 449 |
439 // Register first_non_prealloc is the offset of the first field after | 450 // Register first_non_prealloc is the offset of the first field after |
440 // pre-allocated fields. | 451 // pre-allocated fields. |
441 Register first_non_prealloc = x12; | 452 Register first_non_prealloc = x12; |
442 __ Add(first_non_prealloc, first_prop, | 453 __ Add(first_non_prealloc, first_prop, |
443 Operand(prealloc_fields, LSL, kPointerSizeLog2)); | 454 Operand(prealloc_fields, LSL, kPointerSizeLog2)); |
444 | 455 |
445 first_prop = NoReg; | |
446 | |
447 if (FLAG_debug_code) { | 456 if (FLAG_debug_code) { |
448 Register obj_end = x5; | 457 Register obj_end = x14; |
449 __ Add(obj_end, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); | 458 __ Add(obj_end, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); |
450 __ Cmp(first_non_prealloc, obj_end); | 459 __ Cmp(first_non_prealloc, obj_end); |
451 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); | 460 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); |
452 } | 461 } |
453 | 462 |
454 // Fill the remaining fields with one pointer filler map. | 463 // Fill the remaining fields with one pointer filler map. |
455 Register one_pointer_filler = x5; | 464 Register one_pointer_filler = x14; |
456 Register non_prealloc_fields = x6; | 465 Register non_prealloc_fields = x6; |
457 __ LoadRoot(one_pointer_filler, Heap::kOnePointerFillerMapRootIndex); | 466 __ LoadRoot(one_pointer_filler, Heap::kOnePointerFillerMapRootIndex); |
458 __ Sub(non_prealloc_fields, prop_fields, prealloc_fields); | 467 __ Sub(non_prealloc_fields, prop_fields, prealloc_fields); |
459 __ FillFields(first_non_prealloc, non_prealloc_fields, | 468 __ FillFields(first_non_prealloc, non_prealloc_fields, |
460 one_pointer_filler); | 469 one_pointer_filler); |
461 prop_fields = NoReg; | 470 one_pointer_filler = NoReg; |
462 } else if (create_memento) { | 471 __ B(&done_field_initialization); |
463 // Fill the pre-allocated fields with undef. | 472 |
464 __ FillFields(first_prop, prop_fields, undef); | 473 __ bind(&no_inobject_slack_tracking); |
465 __ Add(first_prop, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); | 474 if (create_memento) { |
466 __ LoadRoot(x14, Heap::kAllocationMementoMapRootIndex); | 475 // Fill the pre-allocated fields with undef. |
467 ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset); | 476 __ FillFields(first_prop, prop_fields, undef); |
468 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); | 477 __ Add(first_prop, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); |
469 // Load the AllocationSite | 478 __ LoadRoot(x14, Heap::kAllocationMementoMapRootIndex); |
470 __ Peek(x14, 2 * kXRegSize); | 479 ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset); |
471 ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); | 480 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); |
472 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); | 481 // Load the AllocationSite |
473 first_prop = NoReg; | 482 __ Peek(x14, 2 * kXRegSize); |
474 } else { | 483 ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); |
475 // Fill all of the property fields with undef. | 484 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); |
476 __ FillFields(first_prop, prop_fields, undef); | 485 first_prop = NoReg; |
477 first_prop = NoReg; | 486 } else { |
478 prop_fields = NoReg; | 487 // Fill all of the property fields with undef. |
| 488 __ FillFields(first_prop, prop_fields, undef); |
| 489 first_prop = NoReg; |
| 490 prop_fields = NoReg; |
| 491 } |
| 492 __ bind(&done_field_initialization); |
479 } | 493 } |
480 | 494 |
481 // Add the object tag to make the JSObject real, so that we can continue | 495 // 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 | 496 // 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 | 497 // failures need to undo the allocation, so that the heap is in a |
484 // consistent state and verifiable. | 498 // consistent state and verifiable. |
485 __ Add(new_obj, new_obj, kHeapObjectTag); | 499 __ Add(new_obj, new_obj, kHeapObjectTag); |
486 | 500 |
487 // Check if a non-empty properties array is needed. Continue with | 501 // Check if a non-empty properties array is needed. Continue with |
488 // allocated object if not, or fall through to runtime call if it is. | 502 // allocated object if not, or fall through to runtime call if it is. |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); | 631 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); |
618 Handle<Code> code = | 632 Handle<Code> code = |
619 masm->isolate()->builtins()->HandleApiCallConstruct(); | 633 masm->isolate()->builtins()->HandleApiCallConstruct(); |
620 __ Call(code, RelocInfo::CODE_TARGET); | 634 __ Call(code, RelocInfo::CODE_TARGET); |
621 } else { | 635 } else { |
622 ParameterCount actual(argc); | 636 ParameterCount actual(argc); |
623 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); | 637 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); |
624 } | 638 } |
625 | 639 |
626 // Store offset of return address for deoptimizer. | 640 // Store offset of return address for deoptimizer. |
627 if (!is_api_function && !count_constructions) { | 641 if (!is_api_function) { |
628 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 642 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
629 } | 643 } |
630 | 644 |
631 // Restore the context from the frame. | 645 // Restore the context from the frame. |
632 // x0: result | 646 // x0: result |
633 // jssp[0]: receiver | 647 // jssp[0]: receiver |
634 // jssp[1]: constructor function | 648 // jssp[1]: constructor function |
635 // jssp[2]: number of arguments (smi-tagged) | 649 // jssp[2]: number of arguments (smi-tagged) |
636 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 650 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
637 | 651 |
(...skipping 30 matching lines...) Expand all Loading... |
668 // Leave construct frame. | 682 // Leave construct frame. |
669 } | 683 } |
670 | 684 |
671 __ DropBySMI(x1); | 685 __ DropBySMI(x1); |
672 __ Drop(1); | 686 __ Drop(1); |
673 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); | 687 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); |
674 __ Ret(); | 688 __ Ret(); |
675 } | 689 } |
676 | 690 |
677 | 691 |
678 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { | |
679 Generate_JSConstructStubHelper(masm, false, true, false); | |
680 } | |
681 | |
682 | |
683 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 692 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
684 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); | 693 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); |
685 } | 694 } |
686 | 695 |
687 | 696 |
688 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 697 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
689 Generate_JSConstructStubHelper(masm, true, false, false); | 698 Generate_JSConstructStubHelper(masm, true, false); |
690 } | 699 } |
691 | 700 |
692 | 701 |
693 // Input: | 702 // Input: |
694 // x0: code entry. | 703 // x0: code entry. |
695 // x1: function. | 704 // x1: function. |
696 // x2: receiver. | 705 // x2: receiver. |
697 // x3: argc. | 706 // x3: argc. |
698 // x4: argv. | 707 // x4: argv. |
699 // Output: | 708 // Output: |
(...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1560 __ Unreachable(); | 1569 __ Unreachable(); |
1561 } | 1570 } |
1562 } | 1571 } |
1563 | 1572 |
1564 | 1573 |
1565 #undef __ | 1574 #undef __ |
1566 | 1575 |
1567 } } // namespace v8::internal | 1576 } } // namespace v8::internal |
1568 | 1577 |
1569 #endif // V8_TARGET_ARCH_ARM | 1578 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |