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 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 if (sp_slot_delta < 0) { | 355 if (sp_slot_delta < 0) { |
356 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); | 356 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); |
357 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 357 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |
358 } | 358 } |
359 if (frame()->needs_frame()) { | 359 if (frame()->needs_frame()) { |
360 __ mov(ebp, MemOperand(ebp, 0)); | 360 __ mov(ebp, MemOperand(ebp, 0)); |
361 } | 361 } |
362 frame_access_state()->SetFrameAccessToSP(); | 362 frame_access_state()->SetFrameAccessToSP(); |
363 } | 363 } |
364 | 364 |
| 365 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
| 366 Register, Register, |
| 367 Register) { |
| 368 // There are not enough temp registers left on ia32 for a call instruction |
| 369 // so we pick some scratch registers and save/restore them manually here. |
| 370 int scratch_count = 3; |
| 371 Register scratch1 = ebx; |
| 372 Register scratch2 = ecx; |
| 373 Register scratch3 = edx; |
| 374 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); |
| 375 Label done; |
| 376 |
| 377 // Check if current frame is an arguments adaptor frame. |
| 378 __ cmp(Operand(ebp, StandardFrameConstants::kContextOffset), |
| 379 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 380 __ j(not_equal, &done, Label::kNear); |
| 381 |
| 382 __ push(scratch1); |
| 383 __ push(scratch2); |
| 384 __ push(scratch3); |
| 385 |
| 386 // Load arguments count from current arguments adaptor frame (note, it |
| 387 // does not include receiver). |
| 388 Register caller_args_count_reg = scratch1; |
| 389 __ mov(caller_args_count_reg, |
| 390 Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 391 __ SmiUntag(caller_args_count_reg); |
| 392 |
| 393 ParameterCount callee_args_count(args_reg); |
| 394 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
| 395 scratch3, ReturnAddressState::kOnStack, scratch_count); |
| 396 __ pop(scratch3); |
| 397 __ pop(scratch2); |
| 398 __ pop(scratch1); |
| 399 |
| 400 __ bind(&done); |
| 401 } |
365 | 402 |
366 // Assembles an instruction after register allocation, producing machine code. | 403 // Assembles an instruction after register allocation, producing machine code. |
367 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 404 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
368 X87OperandConverter i(this, instr); | 405 X87OperandConverter i(this, instr); |
369 | 406 InstructionCode opcode = instr->opcode(); |
370 switch (ArchOpcodeField::decode(instr->opcode())) { | 407 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
| 408 switch (arch_opcode) { |
371 case kArchCallCodeObject: { | 409 case kArchCallCodeObject: { |
372 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 410 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
373 __ VerifyX87StackDepth(1); | 411 __ VerifyX87StackDepth(1); |
374 } | 412 } |
375 __ fstp(0); | 413 __ fstp(0); |
376 EnsureSpaceForLazyDeopt(); | 414 EnsureSpaceForLazyDeopt(); |
377 if (HasImmediateInput(instr, 0)) { | 415 if (HasImmediateInput(instr, 0)) { |
378 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 416 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
379 __ call(code, RelocInfo::CODE_TARGET); | 417 __ call(code, RelocInfo::CODE_TARGET); |
380 } else { | 418 } else { |
(...skipping 11 matching lines...) Expand all Loading... |
392 __ fninit(); | 430 __ fninit(); |
393 if (double_result) { | 431 if (double_result) { |
394 __ fld_d(Operand(esp, 0)); | 432 __ fld_d(Operand(esp, 0)); |
395 __ lea(esp, Operand(esp, kDoubleSize)); | 433 __ lea(esp, Operand(esp, kDoubleSize)); |
396 } else { | 434 } else { |
397 __ fld1(); | 435 __ fld1(); |
398 } | 436 } |
399 frame_access_state()->ClearSPDelta(); | 437 frame_access_state()->ClearSPDelta(); |
400 break; | 438 break; |
401 } | 439 } |
| 440 case kArchTailCallCodeObjectFromJSFunction: |
402 case kArchTailCallCodeObject: { | 441 case kArchTailCallCodeObject: { |
403 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 442 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
404 __ VerifyX87StackDepth(1); | 443 __ VerifyX87StackDepth(1); |
405 } | 444 } |
406 __ fstp(0); | 445 __ fstp(0); |
407 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 446 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
408 AssembleDeconstructActivationRecord(stack_param_delta); | 447 AssembleDeconstructActivationRecord(stack_param_delta); |
| 448 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
| 449 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 450 no_reg, no_reg, no_reg); |
| 451 } |
409 if (HasImmediateInput(instr, 0)) { | 452 if (HasImmediateInput(instr, 0)) { |
410 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 453 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
411 __ jmp(code, RelocInfo::CODE_TARGET); | 454 __ jmp(code, RelocInfo::CODE_TARGET); |
412 } else { | 455 } else { |
413 Register reg = i.InputRegister(0); | 456 Register reg = i.InputRegister(0); |
414 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 457 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
415 __ jmp(reg); | 458 __ jmp(reg); |
416 } | 459 } |
417 frame_access_state()->ClearSPDelta(); | 460 frame_access_state()->ClearSPDelta(); |
418 break; | 461 break; |
(...skipping 21 matching lines...) Expand all Loading... |
440 __ fninit(); | 483 __ fninit(); |
441 if (double_result) { | 484 if (double_result) { |
442 __ fld_d(Operand(esp, 0)); | 485 __ fld_d(Operand(esp, 0)); |
443 __ lea(esp, Operand(esp, kDoubleSize)); | 486 __ lea(esp, Operand(esp, kDoubleSize)); |
444 } else { | 487 } else { |
445 __ fld1(); | 488 __ fld1(); |
446 } | 489 } |
447 frame_access_state()->ClearSPDelta(); | 490 frame_access_state()->ClearSPDelta(); |
448 break; | 491 break; |
449 } | 492 } |
| 493 case kArchTailCallJSFunctionFromJSFunction: |
450 case kArchTailCallJSFunction: { | 494 case kArchTailCallJSFunction: { |
451 Register func = i.InputRegister(0); | 495 Register func = i.InputRegister(0); |
452 if (FLAG_debug_code) { | 496 if (FLAG_debug_code) { |
453 // Check the function's context matches the context argument. | 497 // Check the function's context matches the context argument. |
454 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 498 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
455 __ Assert(equal, kWrongFunctionContext); | 499 __ Assert(equal, kWrongFunctionContext); |
456 } | 500 } |
457 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 501 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
458 __ VerifyX87StackDepth(1); | 502 __ VerifyX87StackDepth(1); |
459 } | 503 } |
460 __ fstp(0); | 504 __ fstp(0); |
461 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 505 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
462 AssembleDeconstructActivationRecord(stack_param_delta); | 506 AssembleDeconstructActivationRecord(stack_param_delta); |
| 507 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
| 508 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 509 no_reg, no_reg, no_reg); |
| 510 } |
463 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 511 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
464 frame_access_state()->ClearSPDelta(); | 512 frame_access_state()->ClearSPDelta(); |
465 break; | 513 break; |
466 } | 514 } |
467 case kArchPrepareCallCFunction: { | 515 case kArchPrepareCallCFunction: { |
468 // Frame alignment requires using FP-relative frame addressing. | 516 // Frame alignment requires using FP-relative frame addressing. |
469 frame_access_state()->SetFrameAccessToFP(); | 517 frame_access_state()->SetFrameAccessToFP(); |
470 int const num_parameters = MiscField::decode(instr->opcode()); | 518 int const num_parameters = MiscField::decode(instr->opcode()); |
471 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); | 519 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); |
472 break; | 520 break; |
(...skipping 1821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2294 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2342 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
2295 __ Nop(padding_size); | 2343 __ Nop(padding_size); |
2296 } | 2344 } |
2297 } | 2345 } |
2298 | 2346 |
2299 #undef __ | 2347 #undef __ |
2300 | 2348 |
2301 } // namespace compiler | 2349 } // namespace compiler |
2302 } // namespace internal | 2350 } // namespace internal |
2303 } // namespace v8 | 2351 } // namespace v8 |
OLD | NEW |