| 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 |