OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_ARM | 7 #if V8_TARGET_ARCH_ARM |
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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 // o pp: our caller's constant pool pointer (if FLAG_enable_ool_constant_pool) | 100 // o pp: our caller's constant pool pointer (if FLAG_enable_ool_constant_pool) |
101 // o fp: our caller's frame pointer | 101 // o fp: our caller's frame pointer |
102 // o sp: stack pointer | 102 // o sp: stack pointer |
103 // o lr: return address | 103 // o lr: return address |
104 // | 104 // |
105 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 105 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
106 // frames-arm.h for its layout. | 106 // frames-arm.h for its layout. |
107 void FullCodeGenerator::Generate() { | 107 void FullCodeGenerator::Generate() { |
108 CompilationInfo* info = info_; | 108 CompilationInfo* info = info_; |
109 handler_table_ = | 109 handler_table_ = |
110 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); | 110 Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray( |
| 111 HandlerTable::LengthForRange(function()->handler_count()), TENURED)); |
111 | 112 |
112 profiling_counter_ = isolate()->factory()->NewCell( | 113 profiling_counter_ = isolate()->factory()->NewCell( |
113 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); | 114 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); |
114 SetFunctionPosition(function()); | 115 SetFunctionPosition(function()); |
115 Comment cmnt(masm_, "[ function compiled by full code generator"); | 116 Comment cmnt(masm_, "[ function compiled by full code generator"); |
116 | 117 |
117 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 118 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
118 | 119 |
119 #ifdef DEBUG | 120 #ifdef DEBUG |
120 if (strlen(FLAG_stop_at) > 0 && | 121 if (strlen(FLAG_stop_at) > 0 && |
(...skipping 2068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2189 Label l_next, l_call, l_loop; | 2190 Label l_next, l_call, l_loop; |
2190 Register load_receiver = LoadDescriptor::ReceiverRegister(); | 2191 Register load_receiver = LoadDescriptor::ReceiverRegister(); |
2191 Register load_name = LoadDescriptor::NameRegister(); | 2192 Register load_name = LoadDescriptor::NameRegister(); |
2192 | 2193 |
2193 // Initial send value is undefined. | 2194 // Initial send value is undefined. |
2194 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 2195 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
2195 __ b(&l_next); | 2196 __ b(&l_next); |
2196 | 2197 |
2197 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2198 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
2198 __ bind(&l_catch); | 2199 __ bind(&l_catch); |
2199 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | |
2200 __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" | 2200 __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" |
2201 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2201 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
2202 __ Push(load_name, r3, r0); // "throw", iter, except | 2202 __ Push(load_name, r3, r0); // "throw", iter, except |
2203 __ jmp(&l_call); | 2203 __ jmp(&l_call); |
2204 | 2204 |
2205 // try { received = %yield result } | 2205 // try { received = %yield result } |
2206 // Shuffle the received result above a try handler and yield it without | 2206 // Shuffle the received result above a try handler and yield it without |
2207 // re-boxing. | 2207 // re-boxing. |
2208 __ bind(&l_try); | 2208 __ bind(&l_try); |
2209 __ pop(r0); // result | 2209 __ pop(r0); // result |
2210 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2210 EnterTryBlock(expr->index(), &l_catch); |
2211 const int handler_size = StackHandlerConstants::kSize; | 2211 const int try_block_size = TryCatch::kElementCount * kPointerSize; |
2212 __ push(r0); // result | 2212 __ push(r0); // result |
2213 __ jmp(&l_suspend); | 2213 __ jmp(&l_suspend); |
2214 __ bind(&l_continuation); | 2214 __ bind(&l_continuation); |
2215 __ jmp(&l_resume); | 2215 __ jmp(&l_resume); |
2216 __ bind(&l_suspend); | 2216 __ bind(&l_suspend); |
2217 const int generator_object_depth = kPointerSize + handler_size; | 2217 const int generator_object_depth = kPointerSize + try_block_size; |
2218 __ ldr(r0, MemOperand(sp, generator_object_depth)); | 2218 __ ldr(r0, MemOperand(sp, generator_object_depth)); |
2219 __ push(r0); // g | 2219 __ push(r0); // g |
| 2220 __ Push(Smi::FromInt(expr->index())); // handler-index |
2220 DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 2221 DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
2221 __ mov(r1, Operand(Smi::FromInt(l_continuation.pos()))); | 2222 __ mov(r1, Operand(Smi::FromInt(l_continuation.pos()))); |
2222 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); | 2223 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); |
2223 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); | 2224 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); |
2224 __ mov(r1, cp); | 2225 __ mov(r1, cp); |
2225 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, | 2226 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, |
2226 kLRHasBeenSaved, kDontSaveFPRegs); | 2227 kLRHasBeenSaved, kDontSaveFPRegs); |
2227 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2228 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2); |
2228 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2229 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2229 __ pop(r0); // result | 2230 __ pop(r0); // result |
2230 EmitReturnSequence(); | 2231 EmitReturnSequence(); |
2231 __ bind(&l_resume); // received in r0 | 2232 __ bind(&l_resume); // received in r0 |
2232 __ PopTryHandler(); | 2233 ExitTryBlock(expr->index()); |
2233 | 2234 |
2234 // receiver = iter; f = 'next'; arg = received; | 2235 // receiver = iter; f = 'next'; arg = received; |
2235 __ bind(&l_next); | 2236 __ bind(&l_next); |
2236 | 2237 |
2237 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" | 2238 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" |
2238 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2239 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
2239 __ Push(load_name, r3, r0); // "next", iter, received | 2240 __ Push(load_name, r3, r0); // "next", iter, received |
2240 | 2241 |
2241 // result = receiver[f](arg); | 2242 // result = receiver[f](arg); |
2242 __ bind(&l_call); | 2243 __ bind(&l_call); |
(...skipping 3104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5347 | 5348 |
5348 // Uncook return address and return. | 5349 // Uncook return address and return. |
5349 __ pop(result_register()); | 5350 __ pop(result_register()); |
5350 __ SmiUntag(r1); | 5351 __ SmiUntag(r1); |
5351 __ add(pc, r1, Operand(masm_->CodeObject())); | 5352 __ add(pc, r1, Operand(masm_->CodeObject())); |
5352 } | 5353 } |
5353 | 5354 |
5354 | 5355 |
5355 #undef __ | 5356 #undef __ |
5356 | 5357 |
5357 #define __ ACCESS_MASM(masm()) | |
5358 | |
5359 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( | |
5360 int* stack_depth, | |
5361 int* context_length) { | |
5362 // The macros used here must preserve the result register. | |
5363 | |
5364 // Because the handler block contains the context of the finally | |
5365 // code, we can restore it directly from there for the finally code | |
5366 // rather than iteratively unwinding contexts via their previous | |
5367 // links. | |
5368 __ Drop(*stack_depth); // Down to the handler block. | |
5369 if (*context_length > 0) { | |
5370 // Restore the context to its dedicated register and the stack. | |
5371 __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset)); | |
5372 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
5373 } | |
5374 __ PopTryHandler(); | |
5375 __ bl(finally_entry_); | |
5376 | |
5377 *stack_depth = 0; | |
5378 *context_length = 0; | |
5379 return previous_; | |
5380 } | |
5381 | |
5382 | |
5383 #undef __ | |
5384 | |
5385 | 5358 |
5386 static Address GetInterruptImmediateLoadAddress(Address pc) { | 5359 static Address GetInterruptImmediateLoadAddress(Address pc) { |
5387 Address load_address = pc - 2 * Assembler::kInstrSize; | 5360 Address load_address = pc - 2 * Assembler::kInstrSize; |
5388 if (!FLAG_enable_ool_constant_pool) { | 5361 if (!FLAG_enable_ool_constant_pool) { |
5389 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address))); | 5362 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address))); |
5390 } else if (Assembler::IsLdrPpRegOffset(Memory::int32_at(load_address))) { | 5363 } else if (Assembler::IsLdrPpRegOffset(Memory::int32_at(load_address))) { |
5391 // This is an extended constant pool lookup. | 5364 // This is an extended constant pool lookup. |
5392 if (CpuFeatures::IsSupported(ARMv7)) { | 5365 if (CpuFeatures::IsSupported(ARMv7)) { |
5393 load_address -= 2 * Assembler::kInstrSize; | 5366 load_address -= 2 * Assembler::kInstrSize; |
5394 DCHECK(Assembler::IsMovW(Memory::int32_at(load_address))); | 5367 DCHECK(Assembler::IsMovW(Memory::int32_at(load_address))); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5518 | 5491 |
5519 DCHECK(interrupt_address == | 5492 DCHECK(interrupt_address == |
5520 isolate->builtins()->OsrAfterStackCheck()->entry()); | 5493 isolate->builtins()->OsrAfterStackCheck()->entry()); |
5521 return OSR_AFTER_STACK_CHECK; | 5494 return OSR_AFTER_STACK_CHECK; |
5522 } | 5495 } |
5523 | 5496 |
5524 | 5497 |
5525 } } // namespace v8::internal | 5498 } } // namespace v8::internal |
5526 | 5499 |
5527 #endif // V8_TARGET_ARCH_ARM | 5500 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |