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