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/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 if (sp_slot_delta < 0) { | 348 if (sp_slot_delta < 0) { |
349 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); | 349 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); |
350 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 350 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |
351 } | 351 } |
352 if (frame()->needs_frame()) { | 352 if (frame()->needs_frame()) { |
353 __ mov(ebp, MemOperand(ebp, 0)); | 353 __ mov(ebp, MemOperand(ebp, 0)); |
354 } | 354 } |
355 frame_access_state()->SetFrameAccessToSP(); | 355 frame_access_state()->SetFrameAccessToSP(); |
356 } | 356 } |
357 | 357 |
| 358 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
| 359 Register, Register, |
| 360 Register) { |
| 361 // There are not enough temp registers left on ia32 for a call instruction |
| 362 // so we pick some scratch registers and save/restore them manually here. |
| 363 int scratch_count = 3; |
| 364 Register scratch1 = ebx; |
| 365 Register scratch2 = ecx; |
| 366 Register scratch3 = edx; |
| 367 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); |
| 368 Label done; |
| 369 |
| 370 // Check if current frame is an arguments adaptor frame. |
| 371 __ cmp(Operand(ebp, StandardFrameConstants::kContextOffset), |
| 372 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 373 __ j(not_equal, &done, Label::kNear); |
| 374 |
| 375 __ push(scratch1); |
| 376 __ push(scratch2); |
| 377 __ push(scratch3); |
| 378 |
| 379 // Load arguments count from current arguments adaptor frame (note, it |
| 380 // does not include receiver). |
| 381 Register caller_args_count_reg = scratch1; |
| 382 __ mov(caller_args_count_reg, |
| 383 Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 384 __ SmiUntag(caller_args_count_reg); |
| 385 |
| 386 ParameterCount callee_args_count(args_reg); |
| 387 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
| 388 scratch3, ReturnAddressState::kOnStack, scratch_count); |
| 389 __ pop(scratch3); |
| 390 __ pop(scratch2); |
| 391 __ pop(scratch1); |
| 392 |
| 393 __ bind(&done); |
| 394 } |
358 | 395 |
359 // Assembles an instruction after register allocation, producing machine code. | 396 // Assembles an instruction after register allocation, producing machine code. |
360 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 397 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
361 IA32OperandConverter i(this, instr); | 398 IA32OperandConverter i(this, instr); |
362 | 399 |
363 switch (ArchOpcodeField::decode(instr->opcode())) { | 400 switch (ArchOpcodeField::decode(instr->opcode())) { |
364 case kArchCallCodeObject: { | 401 case kArchCallCodeObject: { |
365 EnsureSpaceForLazyDeopt(); | 402 EnsureSpaceForLazyDeopt(); |
366 if (HasImmediateInput(instr, 0)) { | 403 if (HasImmediateInput(instr, 0)) { |
367 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 404 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
368 __ call(code, RelocInfo::CODE_TARGET); | 405 __ call(code, RelocInfo::CODE_TARGET); |
369 } else { | 406 } else { |
370 Register reg = i.InputRegister(0); | 407 Register reg = i.InputRegister(0); |
371 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 408 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
372 __ call(reg); | 409 __ call(reg); |
373 } | 410 } |
374 RecordCallPosition(instr); | 411 RecordCallPosition(instr); |
375 frame_access_state()->ClearSPDelta(); | 412 frame_access_state()->ClearSPDelta(); |
376 break; | 413 break; |
377 } | 414 } |
| 415 case kArchTailCallCodeObjectFromJSFunction: { |
| 416 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 417 AssembleDeconstructActivationRecord(stack_param_delta); |
| 418 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, no_reg, |
| 419 no_reg, no_reg); |
| 420 if (HasImmediateInput(instr, 0)) { |
| 421 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
| 422 __ jmp(code, RelocInfo::CODE_TARGET); |
| 423 } else { |
| 424 Register reg = i.InputRegister(0); |
| 425 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 426 __ jmp(reg); |
| 427 } |
| 428 frame_access_state()->ClearSPDelta(); |
| 429 break; |
| 430 } |
378 case kArchTailCallCodeObject: { | 431 case kArchTailCallCodeObject: { |
379 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 432 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
380 AssembleDeconstructActivationRecord(stack_param_delta); | 433 AssembleDeconstructActivationRecord(stack_param_delta); |
381 if (HasImmediateInput(instr, 0)) { | 434 if (HasImmediateInput(instr, 0)) { |
382 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 435 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
383 __ jmp(code, RelocInfo::CODE_TARGET); | 436 __ jmp(code, RelocInfo::CODE_TARGET); |
384 } else { | 437 } else { |
385 Register reg = i.InputRegister(0); | 438 Register reg = i.InputRegister(0); |
386 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 439 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
387 __ jmp(reg); | 440 __ jmp(reg); |
388 } | 441 } |
389 frame_access_state()->ClearSPDelta(); | 442 frame_access_state()->ClearSPDelta(); |
390 break; | 443 break; |
391 } | 444 } |
392 case kArchCallJSFunction: { | 445 case kArchCallJSFunction: { |
393 EnsureSpaceForLazyDeopt(); | 446 EnsureSpaceForLazyDeopt(); |
394 Register func = i.InputRegister(0); | 447 Register func = i.InputRegister(0); |
395 if (FLAG_debug_code) { | 448 if (FLAG_debug_code) { |
396 // Check the function's context matches the context argument. | 449 // Check the function's context matches the context argument. |
397 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 450 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
398 __ Assert(equal, kWrongFunctionContext); | 451 __ Assert(equal, kWrongFunctionContext); |
399 } | 452 } |
400 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 453 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
401 RecordCallPosition(instr); | 454 RecordCallPosition(instr); |
402 frame_access_state()->ClearSPDelta(); | 455 frame_access_state()->ClearSPDelta(); |
403 break; | 456 break; |
404 } | 457 } |
| 458 case kArchTailCallJSFunctionFromJSFunction: { |
| 459 Register func = i.InputRegister(0); |
| 460 if (FLAG_debug_code) { |
| 461 // Check the function's context matches the context argument. |
| 462 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
| 463 __ Assert(equal, kWrongFunctionContext); |
| 464 } |
| 465 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 466 AssembleDeconstructActivationRecord(stack_param_delta); |
| 467 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, no_reg, |
| 468 no_reg, no_reg); |
| 469 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
| 470 frame_access_state()->ClearSPDelta(); |
| 471 break; |
| 472 } |
405 case kArchTailCallJSFunction: { | 473 case kArchTailCallJSFunction: { |
406 Register func = i.InputRegister(0); | 474 Register func = i.InputRegister(0); |
407 if (FLAG_debug_code) { | 475 if (FLAG_debug_code) { |
408 // Check the function's context matches the context argument. | 476 // Check the function's context matches the context argument. |
409 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 477 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
410 __ Assert(equal, kWrongFunctionContext); | 478 __ Assert(equal, kWrongFunctionContext); |
411 } | 479 } |
412 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 480 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
413 AssembleDeconstructActivationRecord(stack_param_delta); | 481 AssembleDeconstructActivationRecord(stack_param_delta); |
414 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 482 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1756 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 1824 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
1757 __ Nop(padding_size); | 1825 __ Nop(padding_size); |
1758 } | 1826 } |
1759 } | 1827 } |
1760 | 1828 |
1761 #undef __ | 1829 #undef __ |
1762 | 1830 |
1763 } // namespace compiler | 1831 } // namespace compiler |
1764 } // namespace internal | 1832 } // namespace internal |
1765 } // namespace v8 | 1833 } // namespace v8 |
OLD | NEW |