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