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 InstructionCode opcode = instr->opcode(); |
363 switch (ArchOpcodeField::decode(instr->opcode())) { | 400 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
| 401 switch (arch_opcode) { |
364 case kArchCallCodeObject: { | 402 case kArchCallCodeObject: { |
365 EnsureSpaceForLazyDeopt(); | 403 EnsureSpaceForLazyDeopt(); |
366 if (HasImmediateInput(instr, 0)) { | 404 if (HasImmediateInput(instr, 0)) { |
367 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 405 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
368 __ call(code, RelocInfo::CODE_TARGET); | 406 __ call(code, RelocInfo::CODE_TARGET); |
369 } else { | 407 } else { |
370 Register reg = i.InputRegister(0); | 408 Register reg = i.InputRegister(0); |
371 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 409 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
372 __ call(reg); | 410 __ call(reg); |
373 } | 411 } |
374 RecordCallPosition(instr); | 412 RecordCallPosition(instr); |
375 frame_access_state()->ClearSPDelta(); | 413 frame_access_state()->ClearSPDelta(); |
376 break; | 414 break; |
377 } | 415 } |
| 416 case kArchTailCallCodeObjectFromJSFunction: |
378 case kArchTailCallCodeObject: { | 417 case kArchTailCallCodeObject: { |
379 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 418 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
380 AssembleDeconstructActivationRecord(stack_param_delta); | 419 AssembleDeconstructActivationRecord(stack_param_delta); |
| 420 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
| 421 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 422 no_reg, no_reg, no_reg); |
| 423 } |
381 if (HasImmediateInput(instr, 0)) { | 424 if (HasImmediateInput(instr, 0)) { |
382 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 425 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
383 __ jmp(code, RelocInfo::CODE_TARGET); | 426 __ jmp(code, RelocInfo::CODE_TARGET); |
384 } else { | 427 } else { |
385 Register reg = i.InputRegister(0); | 428 Register reg = i.InputRegister(0); |
386 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 429 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
387 __ jmp(reg); | 430 __ jmp(reg); |
388 } | 431 } |
389 frame_access_state()->ClearSPDelta(); | 432 frame_access_state()->ClearSPDelta(); |
390 break; | 433 break; |
391 } | 434 } |
392 case kArchCallJSFunction: { | 435 case kArchCallJSFunction: { |
393 EnsureSpaceForLazyDeopt(); | 436 EnsureSpaceForLazyDeopt(); |
394 Register func = i.InputRegister(0); | 437 Register func = i.InputRegister(0); |
395 if (FLAG_debug_code) { | 438 if (FLAG_debug_code) { |
396 // Check the function's context matches the context argument. | 439 // Check the function's context matches the context argument. |
397 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 440 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
398 __ Assert(equal, kWrongFunctionContext); | 441 __ Assert(equal, kWrongFunctionContext); |
399 } | 442 } |
400 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 443 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
401 RecordCallPosition(instr); | 444 RecordCallPosition(instr); |
402 frame_access_state()->ClearSPDelta(); | 445 frame_access_state()->ClearSPDelta(); |
403 break; | 446 break; |
404 } | 447 } |
| 448 case kArchTailCallJSFunctionFromJSFunction: |
405 case kArchTailCallJSFunction: { | 449 case kArchTailCallJSFunction: { |
406 Register func = i.InputRegister(0); | 450 Register func = i.InputRegister(0); |
407 if (FLAG_debug_code) { | 451 if (FLAG_debug_code) { |
408 // Check the function's context matches the context argument. | 452 // Check the function's context matches the context argument. |
409 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 453 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
410 __ Assert(equal, kWrongFunctionContext); | 454 __ Assert(equal, kWrongFunctionContext); |
411 } | 455 } |
412 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 456 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
413 AssembleDeconstructActivationRecord(stack_param_delta); | 457 AssembleDeconstructActivationRecord(stack_param_delta); |
| 458 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
| 459 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 460 no_reg, no_reg, no_reg); |
| 461 } |
414 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 462 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
415 frame_access_state()->ClearSPDelta(); | 463 frame_access_state()->ClearSPDelta(); |
416 break; | 464 break; |
417 } | 465 } |
418 case kArchPrepareCallCFunction: { | 466 case kArchPrepareCallCFunction: { |
419 // Frame alignment requires using FP-relative frame addressing. | 467 // Frame alignment requires using FP-relative frame addressing. |
420 frame_access_state()->SetFrameAccessToFP(); | 468 frame_access_state()->SetFrameAccessToFP(); |
421 int const num_parameters = MiscField::decode(instr->opcode()); | 469 int const num_parameters = MiscField::decode(instr->opcode()); |
422 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); | 470 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); |
423 break; | 471 break; |
(...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1756 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 1804 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
1757 __ Nop(padding_size); | 1805 __ Nop(padding_size); |
1758 } | 1806 } |
1759 } | 1807 } |
1760 | 1808 |
1761 #undef __ | 1809 #undef __ |
1762 | 1810 |
1763 } // namespace compiler | 1811 } // namespace compiler |
1764 } // namespace internal | 1812 } // namespace internal |
1765 } // namespace v8 | 1813 } // namespace v8 |
OLD | NEW |