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/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
| 10 #include "src/compiler/osr.h" |
10 #include "src/ia32/assembler-ia32.h" | 11 #include "src/ia32/assembler-ia32.h" |
11 #include "src/ia32/frames-ia32.h" | 12 #include "src/ia32/frames-ia32.h" |
12 #include "src/ia32/macro-assembler-ia32.h" | 13 #include "src/ia32/macro-assembler-ia32.h" |
13 #include "src/scopes.h" | 14 #include "src/scopes.h" |
14 | 15 |
15 namespace v8 { | 16 namespace v8 { |
16 namespace internal { | 17 namespace internal { |
17 namespace compiler { | 18 namespace compiler { |
18 | 19 |
19 #define __ masm()-> | 20 #define __ masm()-> |
(...skipping 1230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1250 // | FP | RET | args | caller frame | | 1251 // | FP | RET | args | caller frame | |
1251 // ^ esp,ebp | 1252 // ^ esp,ebp |
1252 | 1253 |
1253 // --{ pop ebp }---------------------------------------------------------------- | 1254 // --{ pop ebp }---------------------------------------------------------------- |
1254 // | RET | args | caller frame | | 1255 // | RET | args | caller frame | |
1255 // ^ esp ^ ebp | 1256 // ^ esp ^ ebp |
1256 | 1257 |
1257 | 1258 |
1258 void CodeGenerator::AssemblePrologue() { | 1259 void CodeGenerator::AssemblePrologue() { |
1259 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1260 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
1260 int stack_slots = frame()->GetSpillSlotCount(); | |
1261 if (descriptor->kind() == CallDescriptor::kCallAddress) { | 1261 if (descriptor->kind() == CallDescriptor::kCallAddress) { |
1262 // Assemble a prologue similar the to cdecl calling convention. | 1262 // Assemble a prologue similar the to cdecl calling convention. |
1263 __ push(ebp); | 1263 __ push(ebp); |
1264 __ mov(ebp, esp); | 1264 __ mov(ebp, esp); |
1265 const RegList saves = descriptor->CalleeSavedRegisters(); | |
1266 if (saves != 0) { // Save callee-saved registers. | |
1267 int register_save_area_size = 0; | |
1268 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { | |
1269 if (!((1 << i) & saves)) continue; | |
1270 __ push(Register::from_code(i)); | |
1271 register_save_area_size += kPointerSize; | |
1272 } | |
1273 frame()->SetRegisterSaveAreaSize(register_save_area_size); | |
1274 } | |
1275 } else if (descriptor->IsJSFunctionCall()) { | 1265 } else if (descriptor->IsJSFunctionCall()) { |
1276 // TODO(turbofan): this prologue is redundant with OSR, but needed for | 1266 // TODO(turbofan): this prologue is redundant with OSR, but needed for |
1277 // code aging. | 1267 // code aging. |
1278 CompilationInfo* info = this->info(); | 1268 CompilationInfo* info = this->info(); |
1279 __ Prologue(info->IsCodePreAgingActive()); | 1269 __ Prologue(info->IsCodePreAgingActive()); |
1280 frame()->SetRegisterSaveAreaSize( | |
1281 StandardFrameConstants::kFixedFrameSizeFromFp); | |
1282 } else if (needs_frame_) { | 1270 } else if (needs_frame_) { |
1283 __ StubPrologue(); | 1271 __ StubPrologue(); |
1284 frame()->SetRegisterSaveAreaSize( | 1272 } else { |
1285 StandardFrameConstants::kFixedFrameSizeFromFp); | 1273 frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize); |
1286 } | 1274 } |
1287 | 1275 |
| 1276 int stack_shrink_slots = frame()->GetSpillSlotCount(); |
1288 if (info()->is_osr()) { | 1277 if (info()->is_osr()) { |
1289 // TurboFan OSR-compiled functions cannot be entered directly. | 1278 // TurboFan OSR-compiled functions cannot be entered directly. |
1290 __ Abort(kShouldNotDirectlyEnterOsrFunction); | 1279 __ Abort(kShouldNotDirectlyEnterOsrFunction); |
1291 | 1280 |
1292 // Unoptimized code jumps directly to this entrypoint while the unoptimized | 1281 // Unoptimized code jumps directly to this entrypoint while the unoptimized |
1293 // frame is still on the stack. Optimized code uses OSR values directly from | 1282 // frame is still on the stack. Optimized code uses OSR values directly from |
1294 // the unoptimized frame. Thus, all that needs to be done is to allocate the | 1283 // the unoptimized frame. Thus, all that needs to be done is to allocate the |
1295 // remaining stack slots. | 1284 // remaining stack slots. |
1296 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); | 1285 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); |
1297 osr_pc_offset_ = __ pc_offset(); | 1286 osr_pc_offset_ = __ pc_offset(); |
1298 // TODO(titzer): cannot address target function == local #-1 | 1287 // TODO(titzer): cannot address target function == local #-1 |
1299 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1288 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1300 DCHECK(stack_slots >= frame()->GetOsrStackSlotCount()); | 1289 stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots(); |
1301 stack_slots -= frame()->GetOsrStackSlotCount(); | |
1302 } | 1290 } |
1303 | 1291 |
1304 if (stack_slots > 0) { | 1292 const RegList saves = descriptor->CalleeSavedRegisters(); |
1305 // Allocate the stack slots used by this frame. | 1293 if (stack_shrink_slots > 0) { |
1306 __ sub(esp, Immediate(stack_slots * kPointerSize)); | 1294 __ sub(esp, Immediate(stack_shrink_slots * kPointerSize)); |
| 1295 } |
| 1296 |
| 1297 if (saves != 0) { // Save callee-saved registers. |
| 1298 DCHECK(!info()->is_osr()); |
| 1299 int pushed = 0; |
| 1300 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { |
| 1301 if (!((1 << i) & saves)) continue; |
| 1302 __ push(Register::from_code(i)); |
| 1303 ++pushed; |
| 1304 } |
| 1305 frame()->AllocateSavedCalleeRegisterSlots(pushed); |
1307 } | 1306 } |
1308 } | 1307 } |
1309 | 1308 |
1310 | 1309 |
1311 void CodeGenerator::AssembleReturn() { | 1310 void CodeGenerator::AssembleReturn() { |
1312 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1311 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
1313 int stack_slots = frame()->GetSpillSlotCount(); | 1312 |
| 1313 const RegList saves = descriptor->CalleeSavedRegisters(); |
| 1314 // Restore registers. |
| 1315 if (saves != 0) { |
| 1316 for (int i = 0; i < Register::kNumRegisters; i++) { |
| 1317 if (!((1 << i) & saves)) continue; |
| 1318 __ pop(Register::from_code(i)); |
| 1319 } |
| 1320 } |
| 1321 |
1314 if (descriptor->kind() == CallDescriptor::kCallAddress) { | 1322 if (descriptor->kind() == CallDescriptor::kCallAddress) { |
1315 const RegList saves = descriptor->CalleeSavedRegisters(); | 1323 __ mov(esp, ebp); // Move stack pointer back to frame pointer. |
1316 if (frame()->GetRegisterSaveAreaSize() > 0) { | 1324 __ pop(ebp); // Pop caller's frame pointer. |
1317 // Remove this frame's spill slots first. | |
1318 if (stack_slots > 0) { | |
1319 __ add(esp, Immediate(stack_slots * kPointerSize)); | |
1320 } | |
1321 // Restore registers. | |
1322 if (saves != 0) { | |
1323 for (int i = 0; i < Register::kNumRegisters; i++) { | |
1324 if (!((1 << i) & saves)) continue; | |
1325 __ pop(Register::from_code(i)); | |
1326 } | |
1327 } | |
1328 __ pop(ebp); // Pop caller's frame pointer. | |
1329 } else { | |
1330 // No saved registers. | |
1331 __ mov(esp, ebp); // Move stack pointer back to frame pointer. | |
1332 __ pop(ebp); // Pop caller's frame pointer. | |
1333 } | |
1334 } else if (descriptor->IsJSFunctionCall() || needs_frame_) { | 1325 } else if (descriptor->IsJSFunctionCall() || needs_frame_) { |
1335 // Canonicalize JSFunction return sites for now. | 1326 // Canonicalize JSFunction return sites for now. |
1336 if (return_label_.is_bound()) { | 1327 if (return_label_.is_bound()) { |
1337 __ jmp(&return_label_); | 1328 __ jmp(&return_label_); |
1338 return; | 1329 return; |
1339 } else { | 1330 } else { |
1340 __ bind(&return_label_); | 1331 __ bind(&return_label_); |
1341 __ mov(esp, ebp); // Move stack pointer back to frame pointer. | 1332 __ mov(esp, ebp); // Move stack pointer back to frame pointer. |
1342 __ pop(ebp); // Pop caller's frame pointer. | 1333 __ pop(ebp); // Pop caller's frame pointer. |
1343 } | 1334 } |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1534 __ Nop(padding_size); | 1525 __ Nop(padding_size); |
1535 } | 1526 } |
1536 } | 1527 } |
1537 } | 1528 } |
1538 | 1529 |
1539 #undef __ | 1530 #undef __ |
1540 | 1531 |
1541 } // namespace compiler | 1532 } // namespace compiler |
1542 } // namespace internal | 1533 } // namespace internal |
1543 } // namespace v8 | 1534 } // namespace v8 |
OLD | NEW |