OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/arm/macro-assembler-arm.h" | 7 #include "src/arm/macro-assembler-arm.h" |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/compiler/code-generator-impl.h" | 9 #include "src/compiler/code-generator-impl.h" |
10 #include "src/compiler/gap-resolver.h" | 10 #include "src/compiler/gap-resolver.h" |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 if (frame()->needs_frame()) { | 398 if (frame()->needs_frame()) { |
399 if (FLAG_enable_embedded_constant_pool) { | 399 if (FLAG_enable_embedded_constant_pool) { |
400 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); | 400 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); |
401 } | 401 } |
402 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); | 402 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
403 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 403 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
404 } | 404 } |
405 frame_access_state()->SetFrameAccessToSP(); | 405 frame_access_state()->SetFrameAccessToSP(); |
406 } | 406 } |
407 | 407 |
| 408 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
| 409 Register scratch1, |
| 410 Register scratch2, |
| 411 Register scratch3) { |
| 412 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); |
| 413 Label done; |
| 414 |
| 415 // Check if current frame is an arguments adaptor frame. |
| 416 __ ldr(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 417 __ cmp(scratch1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 418 __ b(ne, &done); |
| 419 |
| 420 // Load arguments count from current arguments adaptor frame (note, it |
| 421 // does not include receiver). |
| 422 Register caller_args_count_reg = scratch1; |
| 423 __ ldr(caller_args_count_reg, |
| 424 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 425 __ SmiUntag(caller_args_count_reg); |
| 426 |
| 427 ParameterCount callee_args_count(args_reg); |
| 428 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
| 429 scratch3); |
| 430 __ bind(&done); |
| 431 } |
408 | 432 |
409 // Assembles an instruction after register allocation, producing machine code. | 433 // Assembles an instruction after register allocation, producing machine code. |
410 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 434 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
411 ArmOperandConverter i(this, instr); | 435 ArmOperandConverter i(this, instr); |
412 | 436 |
413 __ MaybeCheckConstPool(); | 437 __ MaybeCheckConstPool(); |
414 | 438 InstructionCode opcode = instr->opcode(); |
415 switch (ArchOpcodeField::decode(instr->opcode())) { | 439 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
| 440 switch (arch_opcode) { |
416 case kArchCallCodeObject: { | 441 case kArchCallCodeObject: { |
417 EnsureSpaceForLazyDeopt(); | 442 EnsureSpaceForLazyDeopt(); |
418 if (instr->InputAt(0)->IsImmediate()) { | 443 if (instr->InputAt(0)->IsImmediate()) { |
419 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 444 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
420 RelocInfo::CODE_TARGET); | 445 RelocInfo::CODE_TARGET); |
421 } else { | 446 } else { |
422 __ add(ip, i.InputRegister(0), | 447 __ add(ip, i.InputRegister(0), |
423 Operand(Code::kHeaderSize - kHeapObjectTag)); | 448 Operand(Code::kHeaderSize - kHeapObjectTag)); |
424 __ Call(ip); | 449 __ Call(ip); |
425 } | 450 } |
426 RecordCallPosition(instr); | 451 RecordCallPosition(instr); |
427 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 452 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
428 frame_access_state()->ClearSPDelta(); | 453 frame_access_state()->ClearSPDelta(); |
429 break; | 454 break; |
430 } | 455 } |
| 456 case kArchTailCallCodeObjectFromJSFunction: |
431 case kArchTailCallCodeObject: { | 457 case kArchTailCallCodeObject: { |
432 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 458 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
433 AssembleDeconstructActivationRecord(stack_param_delta); | 459 AssembleDeconstructActivationRecord(stack_param_delta); |
| 460 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
| 461 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 462 i.TempRegister(0), i.TempRegister(1), |
| 463 i.TempRegister(2)); |
| 464 } |
434 if (instr->InputAt(0)->IsImmediate()) { | 465 if (instr->InputAt(0)->IsImmediate()) { |
435 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 466 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
436 RelocInfo::CODE_TARGET); | 467 RelocInfo::CODE_TARGET); |
437 } else { | 468 } else { |
438 __ add(ip, i.InputRegister(0), | 469 __ add(ip, i.InputRegister(0), |
439 Operand(Code::kHeaderSize - kHeapObjectTag)); | 470 Operand(Code::kHeaderSize - kHeapObjectTag)); |
440 __ Jump(ip); | 471 __ Jump(ip); |
441 } | 472 } |
442 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 473 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
443 frame_access_state()->ClearSPDelta(); | 474 frame_access_state()->ClearSPDelta(); |
444 break; | 475 break; |
445 } | 476 } |
446 case kArchCallJSFunction: { | 477 case kArchCallJSFunction: { |
447 EnsureSpaceForLazyDeopt(); | 478 EnsureSpaceForLazyDeopt(); |
448 Register func = i.InputRegister(0); | 479 Register func = i.InputRegister(0); |
449 if (FLAG_debug_code) { | 480 if (FLAG_debug_code) { |
450 // Check the function's context matches the context argument. | 481 // Check the function's context matches the context argument. |
451 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 482 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
452 __ cmp(cp, kScratchReg); | 483 __ cmp(cp, kScratchReg); |
453 __ Assert(eq, kWrongFunctionContext); | 484 __ Assert(eq, kWrongFunctionContext); |
454 } | 485 } |
455 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 486 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
456 __ Call(ip); | 487 __ Call(ip); |
457 RecordCallPosition(instr); | 488 RecordCallPosition(instr); |
458 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 489 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
459 frame_access_state()->ClearSPDelta(); | 490 frame_access_state()->ClearSPDelta(); |
460 break; | 491 break; |
461 } | 492 } |
| 493 case kArchTailCallJSFunctionFromJSFunction: |
462 case kArchTailCallJSFunction: { | 494 case kArchTailCallJSFunction: { |
463 Register func = i.InputRegister(0); | 495 Register func = i.InputRegister(0); |
464 if (FLAG_debug_code) { | 496 if (FLAG_debug_code) { |
465 // Check the function's context matches the context argument. | 497 // Check the function's context matches the context argument. |
466 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 498 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
467 __ cmp(cp, kScratchReg); | 499 __ cmp(cp, kScratchReg); |
468 __ Assert(eq, kWrongFunctionContext); | 500 __ Assert(eq, kWrongFunctionContext); |
469 } | 501 } |
470 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 502 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
471 AssembleDeconstructActivationRecord(stack_param_delta); | 503 AssembleDeconstructActivationRecord(stack_param_delta); |
| 504 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
| 505 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 506 i.TempRegister(0), i.TempRegister(1), |
| 507 i.TempRegister(2)); |
| 508 } |
472 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 509 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
473 __ Jump(ip); | 510 __ Jump(ip); |
474 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 511 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
475 frame_access_state()->ClearSPDelta(); | 512 frame_access_state()->ClearSPDelta(); |
476 break; | 513 break; |
477 } | 514 } |
478 case kArchPrepareCallCFunction: { | 515 case kArchPrepareCallCFunction: { |
479 int const num_parameters = MiscField::decode(instr->opcode()); | 516 int const num_parameters = MiscField::decode(instr->opcode()); |
480 __ PrepareCallCFunction(num_parameters, kScratchReg); | 517 __ PrepareCallCFunction(num_parameters, kScratchReg); |
481 // Frame alignment requires using FP-relative frame addressing. | 518 // Frame alignment requires using FP-relative frame addressing. |
(...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1472 padding_size -= v8::internal::Assembler::kInstrSize; | 1509 padding_size -= v8::internal::Assembler::kInstrSize; |
1473 } | 1510 } |
1474 } | 1511 } |
1475 } | 1512 } |
1476 | 1513 |
1477 #undef __ | 1514 #undef __ |
1478 | 1515 |
1479 } // namespace compiler | 1516 } // namespace compiler |
1480 } // namespace internal | 1517 } // namespace internal |
1481 } // namespace v8 | 1518 } // namespace v8 |
OLD | NEW |