OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 21 matching lines...) Expand all Loading... |
32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
34 #include "regexp-macro-assembler.h" | 34 #include "regexp-macro-assembler.h" |
35 #include "stub-cache.h" | 35 #include "stub-cache.h" |
36 #include "runtime.h" | 36 #include "runtime.h" |
37 | 37 |
38 namespace v8 { | 38 namespace v8 { |
39 namespace internal { | 39 namespace internal { |
40 | 40 |
41 | 41 |
| 42 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( |
| 43 Isolate* isolate, |
| 44 CodeStubInterfaceDescriptor* descriptor) { |
| 45 static Register registers[] = { rax, rbx, rcx }; |
| 46 descriptor->register_param_count_ = 3; |
| 47 descriptor->register_params_ = registers; |
| 48 descriptor->stack_parameter_count_ = NULL; |
| 49 descriptor->deoptimization_handler_ = |
| 50 Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry; |
| 51 } |
| 52 |
| 53 |
42 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( | 54 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( |
43 Isolate* isolate, | 55 Isolate* isolate, |
44 CodeStubInterfaceDescriptor* descriptor) { | 56 CodeStubInterfaceDescriptor* descriptor) { |
45 static Register registers[] = { rax, rbx, rcx, rdx }; | 57 static Register registers[] = { rax, rbx, rcx, rdx }; |
46 descriptor->register_param_count_ = 4; | 58 descriptor->register_param_count_ = 4; |
47 descriptor->register_params_ = registers; | 59 descriptor->register_params_ = registers; |
48 descriptor->stack_parameter_count_ = NULL; | 60 descriptor->stack_parameter_count_ = NULL; |
49 descriptor->deoptimization_handler_ = | 61 descriptor->deoptimization_handler_ = |
50 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; | 62 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; |
51 } | 63 } |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 // Return and remove the on-stack parameter. | 391 // Return and remove the on-stack parameter. |
380 __ movq(rsi, rax); | 392 __ movq(rsi, rax); |
381 __ ret(2 * kPointerSize); | 393 __ ret(2 * kPointerSize); |
382 | 394 |
383 // Need to collect. Call into runtime system. | 395 // Need to collect. Call into runtime system. |
384 __ bind(&gc); | 396 __ bind(&gc); |
385 __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1); | 397 __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1); |
386 } | 398 } |
387 | 399 |
388 | 400 |
389 static void GenerateFastCloneShallowArrayCommon( | |
390 MacroAssembler* masm, | |
391 int length, | |
392 FastCloneShallowArrayStub::Mode mode, | |
393 AllocationSiteMode allocation_site_mode, | |
394 Label* fail) { | |
395 // Registers on entry: | |
396 // | |
397 // rcx: boilerplate literal array. | |
398 ASSERT(mode != FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS); | |
399 | |
400 // All sizes here are multiples of kPointerSize. | |
401 int elements_size = 0; | |
402 if (length > 0) { | |
403 elements_size = mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS | |
404 ? FixedDoubleArray::SizeFor(length) | |
405 : FixedArray::SizeFor(length); | |
406 } | |
407 int size = JSArray::kSize; | |
408 int allocation_info_start = size; | |
409 if (allocation_site_mode == TRACK_ALLOCATION_SITE) { | |
410 size += AllocationSiteInfo::kSize; | |
411 } | |
412 size += elements_size; | |
413 | |
414 // Allocate both the JS array and the elements array in one big | |
415 // allocation. This avoids multiple limit checks. | |
416 AllocationFlags flags = TAG_OBJECT; | |
417 if (mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS) { | |
418 flags = static_cast<AllocationFlags>(DOUBLE_ALIGNMENT | flags); | |
419 } | |
420 __ Allocate(size, rax, rbx, rdx, fail, flags); | |
421 | |
422 if (allocation_site_mode == TRACK_ALLOCATION_SITE) { | |
423 __ LoadRoot(kScratchRegister, Heap::kAllocationSiteInfoMapRootIndex); | |
424 __ movq(FieldOperand(rax, allocation_info_start), kScratchRegister); | |
425 __ movq(FieldOperand(rax, allocation_info_start + kPointerSize), rcx); | |
426 } | |
427 | |
428 // Copy the JS array part. | |
429 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | |
430 if ((i != JSArray::kElementsOffset) || (length == 0)) { | |
431 __ movq(rbx, FieldOperand(rcx, i)); | |
432 __ movq(FieldOperand(rax, i), rbx); | |
433 } | |
434 } | |
435 | |
436 if (length > 0) { | |
437 // Get hold of the elements array of the boilerplate and setup the | |
438 // elements pointer in the resulting object. | |
439 __ movq(rcx, FieldOperand(rcx, JSArray::kElementsOffset)); | |
440 if (allocation_site_mode == TRACK_ALLOCATION_SITE) { | |
441 __ lea(rdx, Operand(rax, JSArray::kSize + AllocationSiteInfo::kSize)); | |
442 } else { | |
443 __ lea(rdx, Operand(rax, JSArray::kSize)); | |
444 } | |
445 __ movq(FieldOperand(rax, JSArray::kElementsOffset), rdx); | |
446 | |
447 // Copy the elements array. | |
448 if (mode == FastCloneShallowArrayStub::CLONE_ELEMENTS) { | |
449 for (int i = 0; i < elements_size; i += kPointerSize) { | |
450 __ movq(rbx, FieldOperand(rcx, i)); | |
451 __ movq(FieldOperand(rdx, i), rbx); | |
452 } | |
453 } else { | |
454 ASSERT(mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS); | |
455 int i; | |
456 for (i = 0; i < FixedDoubleArray::kHeaderSize; i += kPointerSize) { | |
457 __ movq(rbx, FieldOperand(rcx, i)); | |
458 __ movq(FieldOperand(rdx, i), rbx); | |
459 } | |
460 while (i < elements_size) { | |
461 __ movsd(xmm0, FieldOperand(rcx, i)); | |
462 __ movsd(FieldOperand(rdx, i), xmm0); | |
463 i += kDoubleSize; | |
464 } | |
465 ASSERT(i == elements_size); | |
466 } | |
467 } | |
468 } | |
469 | |
470 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { | |
471 // Stack layout on entry: | |
472 // | |
473 // [rsp + kPointerSize]: constant elements. | |
474 // [rsp + (2 * kPointerSize)]: literal index. | |
475 // [rsp + (3 * kPointerSize)]: literals array. | |
476 | |
477 // Load boilerplate object into rcx and check if we need to create a | |
478 // boilerplate. | |
479 __ movq(rcx, Operand(rsp, 3 * kPointerSize)); | |
480 __ movq(rax, Operand(rsp, 2 * kPointerSize)); | |
481 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2); | |
482 __ movq(rcx, | |
483 FieldOperand(rcx, index.reg, index.scale, FixedArray::kHeaderSize)); | |
484 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); | |
485 Label slow_case; | |
486 __ j(equal, &slow_case); | |
487 | |
488 FastCloneShallowArrayStub::Mode mode = mode_; | |
489 // rcx is boilerplate object. | |
490 Factory* factory = masm->isolate()->factory(); | |
491 if (mode == CLONE_ANY_ELEMENTS) { | |
492 Label double_elements, check_fast_elements; | |
493 __ movq(rbx, FieldOperand(rcx, JSArray::kElementsOffset)); | |
494 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), | |
495 factory->fixed_cow_array_map()); | |
496 __ j(not_equal, &check_fast_elements); | |
497 GenerateFastCloneShallowArrayCommon(masm, 0, COPY_ON_WRITE_ELEMENTS, | |
498 allocation_site_mode_, | |
499 &slow_case); | |
500 __ ret(3 * kPointerSize); | |
501 | |
502 __ bind(&check_fast_elements); | |
503 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), | |
504 factory->fixed_array_map()); | |
505 __ j(not_equal, &double_elements); | |
506 GenerateFastCloneShallowArrayCommon(masm, length_, CLONE_ELEMENTS, | |
507 allocation_site_mode_, | |
508 &slow_case); | |
509 __ ret(3 * kPointerSize); | |
510 | |
511 __ bind(&double_elements); | |
512 mode = CLONE_DOUBLE_ELEMENTS; | |
513 // Fall through to generate the code to handle double elements. | |
514 } | |
515 | |
516 if (FLAG_debug_code) { | |
517 const char* message; | |
518 Heap::RootListIndex expected_map_index; | |
519 if (mode == CLONE_ELEMENTS) { | |
520 message = "Expected (writable) fixed array"; | |
521 expected_map_index = Heap::kFixedArrayMapRootIndex; | |
522 } else if (mode == CLONE_DOUBLE_ELEMENTS) { | |
523 message = "Expected (writable) fixed double array"; | |
524 expected_map_index = Heap::kFixedDoubleArrayMapRootIndex; | |
525 } else { | |
526 ASSERT(mode == COPY_ON_WRITE_ELEMENTS); | |
527 message = "Expected copy-on-write fixed array"; | |
528 expected_map_index = Heap::kFixedCOWArrayMapRootIndex; | |
529 } | |
530 __ push(rcx); | |
531 __ movq(rcx, FieldOperand(rcx, JSArray::kElementsOffset)); | |
532 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | |
533 expected_map_index); | |
534 __ Assert(equal, message); | |
535 __ pop(rcx); | |
536 } | |
537 | |
538 GenerateFastCloneShallowArrayCommon(masm, length_, mode, | |
539 allocation_site_mode_, | |
540 &slow_case); | |
541 __ ret(3 * kPointerSize); | |
542 | |
543 __ bind(&slow_case); | |
544 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); | |
545 } | |
546 | |
547 | |
548 // The stub expects its argument on the stack and returns its result in tos_: | 401 // The stub expects its argument on the stack and returns its result in tos_: |
549 // zero for false, and a non-zero value for true. | 402 // zero for false, and a non-zero value for true. |
550 void ToBooleanStub::Generate(MacroAssembler* masm) { | 403 void ToBooleanStub::Generate(MacroAssembler* masm) { |
551 // This stub overrides SometimesSetsUpAFrame() to return false. That means | 404 // This stub overrides SometimesSetsUpAFrame() to return false. That means |
552 // we cannot call anything that could cause a GC from this stub. | 405 // we cannot call anything that could cause a GC from this stub. |
553 Label patch; | 406 Label patch; |
554 const Register argument = rax; | 407 const Register argument = rax; |
555 const Register map = rdx; | 408 const Register map = rdx; |
556 | 409 |
557 if (!types_.IsEmpty()) { | 410 if (!types_.IsEmpty()) { |
(...skipping 3589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4147 return result_size_ == 1; | 4000 return result_size_ == 1; |
4148 #else | 4001 #else |
4149 return true; | 4002 return true; |
4150 #endif | 4003 #endif |
4151 } | 4004 } |
4152 | 4005 |
4153 | 4006 |
4154 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 4007 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
4155 CEntryStub::GenerateAheadOfTime(isolate); | 4008 CEntryStub::GenerateAheadOfTime(isolate); |
4156 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 4009 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 4010 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
4157 // It is important that the store buffer overflow stubs are generated first. | 4011 // It is important that the store buffer overflow stubs are generated first. |
4158 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | 4012 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); |
4159 } | 4013 } |
4160 | 4014 |
4161 | 4015 |
4162 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 4016 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
4163 } | 4017 } |
4164 | 4018 |
4165 | 4019 |
4166 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { | 4020 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { |
(...skipping 2601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6768 __ StoreNumberToDoubleElements(rax, | 6622 __ StoreNumberToDoubleElements(rax, |
6769 r9, | 6623 r9, |
6770 r11, | 6624 r11, |
6771 xmm0, | 6625 xmm0, |
6772 &slow_elements); | 6626 &slow_elements); |
6773 __ ret(0); | 6627 __ ret(0); |
6774 } | 6628 } |
6775 | 6629 |
6776 | 6630 |
6777 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { | 6631 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { |
6778 ASSERT(!Serializer::enabled()); | 6632 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); |
6779 CEntryStub ces(1, kSaveFPRegs); | |
6780 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | 6633 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); |
6781 int parameter_count_offset = | 6634 int parameter_count_offset = |
6782 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 6635 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
6783 __ movq(rbx, MemOperand(rbp, parameter_count_offset)); | 6636 __ movq(rbx, MemOperand(rbp, parameter_count_offset)); |
6784 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 6637 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
6785 __ pop(rcx); | 6638 __ pop(rcx); |
6786 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE | 6639 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE |
6787 ? kPointerSize | 6640 ? kPointerSize |
6788 : 0; | 6641 : 0; |
6789 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); | 6642 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6856 #endif | 6709 #endif |
6857 | 6710 |
6858 __ Ret(); | 6711 __ Ret(); |
6859 } | 6712 } |
6860 | 6713 |
6861 #undef __ | 6714 #undef __ |
6862 | 6715 |
6863 } } // namespace v8::internal | 6716 } } // namespace v8::internal |
6864 | 6717 |
6865 #endif // V8_TARGET_ARCH_X64 | 6718 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |