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 "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 // - cp: our context. | 98 // - cp: our context. |
99 // - fp: our caller's frame pointer. | 99 // - fp: our caller's frame pointer. |
100 // - jssp: stack pointer. | 100 // - jssp: stack pointer. |
101 // - lr: return address. | 101 // - lr: return address. |
102 // | 102 // |
103 // The function builds a JS frame. See JavaScriptFrameConstants in | 103 // The function builds a JS frame. See JavaScriptFrameConstants in |
104 // frames-arm.h for its layout. | 104 // frames-arm.h for its layout. |
105 void FullCodeGenerator::Generate() { | 105 void FullCodeGenerator::Generate() { |
106 CompilationInfo* info = info_; | 106 CompilationInfo* info = info_; |
107 handler_table_ = | 107 handler_table_ = |
108 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); | 108 Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray( |
| 109 HandlerTable::LengthForRange(function()->handler_count()), TENURED)); |
109 | 110 |
110 profiling_counter_ = isolate()->factory()->NewCell( | 111 profiling_counter_ = isolate()->factory()->NewCell( |
111 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); | 112 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); |
112 SetFunctionPosition(function()); | 113 SetFunctionPosition(function()); |
113 Comment cmnt(masm_, "[ Function compiled by full code generator"); | 114 Comment cmnt(masm_, "[ Function compiled by full code generator"); |
114 | 115 |
115 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 116 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
116 | 117 |
117 #ifdef DEBUG | 118 #ifdef DEBUG |
118 if (strlen(FLAG_stop_at) > 0 && | 119 if (strlen(FLAG_stop_at) > 0 && |
(...skipping 4917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5036 Label l_next, l_call, l_loop; | 5037 Label l_next, l_call, l_loop; |
5037 Register load_receiver = LoadDescriptor::ReceiverRegister(); | 5038 Register load_receiver = LoadDescriptor::ReceiverRegister(); |
5038 Register load_name = LoadDescriptor::NameRegister(); | 5039 Register load_name = LoadDescriptor::NameRegister(); |
5039 | 5040 |
5040 // Initial send value is undefined. | 5041 // Initial send value is undefined. |
5041 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 5042 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
5042 __ B(&l_next); | 5043 __ B(&l_next); |
5043 | 5044 |
5044 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 5045 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
5045 __ Bind(&l_catch); | 5046 __ Bind(&l_catch); |
5046 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | |
5047 __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" | 5047 __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" |
5048 __ Peek(x3, 1 * kPointerSize); // iter | 5048 __ Peek(x3, 1 * kPointerSize); // iter |
5049 __ Push(load_name, x3, x0); // "throw", iter, except | 5049 __ Push(load_name, x3, x0); // "throw", iter, except |
5050 __ B(&l_call); | 5050 __ B(&l_call); |
5051 | 5051 |
5052 // try { received = %yield result } | 5052 // try { received = %yield result } |
5053 // Shuffle the received result above a try handler and yield it without | 5053 // Shuffle the received result above a try handler and yield it without |
5054 // re-boxing. | 5054 // re-boxing. |
5055 __ Bind(&l_try); | 5055 __ Bind(&l_try); |
5056 __ Pop(x0); // result | 5056 __ Pop(x0); // result |
5057 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 5057 EnterTryBlock(expr->index(), &l_catch); |
5058 const int handler_size = StackHandlerConstants::kSize; | 5058 const int try_block_size = TryCatch::kElementCount * kPointerSize; |
5059 __ Push(x0); // result | 5059 __ Push(x0); // result |
5060 __ B(&l_suspend); | 5060 __ B(&l_suspend); |
5061 | 5061 |
5062 // TODO(jbramley): This label is bound here because the following code | 5062 // TODO(jbramley): This label is bound here because the following code |
5063 // looks at its pos(). Is it possible to do something more efficient here, | 5063 // looks at its pos(). Is it possible to do something more efficient here, |
5064 // perhaps using Adr? | 5064 // perhaps using Adr? |
5065 __ Bind(&l_continuation); | 5065 __ Bind(&l_continuation); |
5066 __ B(&l_resume); | 5066 __ B(&l_resume); |
5067 | 5067 |
5068 __ Bind(&l_suspend); | 5068 __ Bind(&l_suspend); |
5069 const int generator_object_depth = kPointerSize + handler_size; | 5069 const int generator_object_depth = kPointerSize + try_block_size; |
5070 __ Peek(x0, generator_object_depth); | 5070 __ Peek(x0, generator_object_depth); |
5071 __ Push(x0); // g | 5071 __ Push(x0); // g |
| 5072 __ Push(Smi::FromInt(expr->index())); // handler-index |
5072 DCHECK((l_continuation.pos() > 0) && Smi::IsValid(l_continuation.pos())); | 5073 DCHECK((l_continuation.pos() > 0) && Smi::IsValid(l_continuation.pos())); |
5073 __ Mov(x1, Smi::FromInt(l_continuation.pos())); | 5074 __ Mov(x1, Smi::FromInt(l_continuation.pos())); |
5074 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); | 5075 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); |
5075 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); | 5076 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); |
5076 __ Mov(x1, cp); | 5077 __ Mov(x1, cp); |
5077 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, | 5078 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, |
5078 kLRHasBeenSaved, kDontSaveFPRegs); | 5079 kLRHasBeenSaved, kDontSaveFPRegs); |
5079 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 5080 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2); |
5080 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 5081 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
5081 __ Pop(x0); // result | 5082 __ Pop(x0); // result |
5082 EmitReturnSequence(); | 5083 EmitReturnSequence(); |
5083 __ Bind(&l_resume); // received in x0 | 5084 __ Bind(&l_resume); // received in x0 |
5084 __ PopTryHandler(); | 5085 ExitTryBlock(expr->index()); |
5085 | 5086 |
5086 // receiver = iter; f = 'next'; arg = received; | 5087 // receiver = iter; f = 'next'; arg = received; |
5087 __ Bind(&l_next); | 5088 __ Bind(&l_next); |
5088 | 5089 |
5089 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" | 5090 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" |
5090 __ Peek(x3, 1 * kPointerSize); // iter | 5091 __ Peek(x3, 1 * kPointerSize); // iter |
5091 __ Push(load_name, x3, x0); // "next", iter, received | 5092 __ Push(load_name, x3, x0); // "next", iter, received |
5092 | 5093 |
5093 // result = receiver[f](arg); | 5094 // result = receiver[f](arg); |
5094 __ Bind(&l_call); | 5095 __ Bind(&l_call); |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5467 return OSR_AFTER_STACK_CHECK; | 5468 return OSR_AFTER_STACK_CHECK; |
5468 } else { | 5469 } else { |
5469 UNREACHABLE(); | 5470 UNREACHABLE(); |
5470 } | 5471 } |
5471 } | 5472 } |
5472 | 5473 |
5473 return INTERRUPT; | 5474 return INTERRUPT; |
5474 } | 5475 } |
5475 | 5476 |
5476 | 5477 |
5477 #define __ ACCESS_MASM(masm()) | |
5478 | |
5479 | |
5480 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( | |
5481 int* stack_depth, | |
5482 int* context_length) { | |
5483 ASM_LOCATION("FullCodeGenerator::TryFinally::Exit"); | |
5484 // The macros used here must preserve the result register. | |
5485 | |
5486 // Because the handler block contains the context of the finally | |
5487 // code, we can restore it directly from there for the finally code | |
5488 // rather than iteratively unwinding contexts via their previous | |
5489 // links. | |
5490 __ Drop(*stack_depth); // Down to the handler block. | |
5491 if (*context_length > 0) { | |
5492 // Restore the context to its dedicated register and the stack. | |
5493 __ Peek(cp, StackHandlerConstants::kContextOffset); | |
5494 __ Str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
5495 } | |
5496 __ PopTryHandler(); | |
5497 __ Bl(finally_entry_); | |
5498 | |
5499 *stack_depth = 0; | |
5500 *context_length = 0; | |
5501 return previous_; | |
5502 } | |
5503 | |
5504 | |
5505 #undef __ | |
5506 | |
5507 | |
5508 } } // namespace v8::internal | 5478 } } // namespace v8::internal |
5509 | 5479 |
5510 #endif // V8_TARGET_ARCH_ARM64 | 5480 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |