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 |
415 switch (ArchOpcodeField::decode(instr->opcode())) { | 439 switch (ArchOpcodeField::decode(instr->opcode())) { |
416 case kArchCallCodeObject: { | 440 case kArchCallCodeObject: { |
417 EnsureSpaceForLazyDeopt(); | 441 EnsureSpaceForLazyDeopt(); |
418 if (instr->InputAt(0)->IsImmediate()) { | 442 if (instr->InputAt(0)->IsImmediate()) { |
419 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 443 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
420 RelocInfo::CODE_TARGET); | 444 RelocInfo::CODE_TARGET); |
421 } else { | 445 } else { |
422 __ add(ip, i.InputRegister(0), | 446 __ add(ip, i.InputRegister(0), |
423 Operand(Code::kHeaderSize - kHeapObjectTag)); | 447 Operand(Code::kHeaderSize - kHeapObjectTag)); |
424 __ Call(ip); | 448 __ Call(ip); |
425 } | 449 } |
426 RecordCallPosition(instr); | 450 RecordCallPosition(instr); |
427 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 451 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
428 frame_access_state()->ClearSPDelta(); | 452 frame_access_state()->ClearSPDelta(); |
429 break; | 453 break; |
430 } | 454 } |
455 case kArchTailCallCodeObjectFromJSFunction: { | |
Michael Starzinger
2016/03/07 21:47:32
suggestion: I would slightly prefer the common cod
Igor Sheludko
2016/03/07 23:19:23
Good idea! Done.
| |
456 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
457 AssembleDeconstructActivationRecord(stack_param_delta); | |
458 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | |
459 i.TempRegister(0), i.TempRegister(1), | |
460 i.TempRegister(2)); | |
461 if (instr->InputAt(0)->IsImmediate()) { | |
462 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | |
463 RelocInfo::CODE_TARGET); | |
464 } else { | |
465 __ add(ip, i.InputRegister(0), | |
466 Operand(Code::kHeaderSize - kHeapObjectTag)); | |
467 __ Jump(ip); | |
468 } | |
469 DCHECK_EQ(LeaveCC, i.OutputSBit()); | |
470 frame_access_state()->ClearSPDelta(); | |
471 break; | |
472 } | |
431 case kArchTailCallCodeObject: { | 473 case kArchTailCallCodeObject: { |
432 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 474 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
433 AssembleDeconstructActivationRecord(stack_param_delta); | 475 AssembleDeconstructActivationRecord(stack_param_delta); |
434 if (instr->InputAt(0)->IsImmediate()) { | 476 if (instr->InputAt(0)->IsImmediate()) { |
435 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 477 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
436 RelocInfo::CODE_TARGET); | 478 RelocInfo::CODE_TARGET); |
437 } else { | 479 } else { |
438 __ add(ip, i.InputRegister(0), | 480 __ add(ip, i.InputRegister(0), |
439 Operand(Code::kHeaderSize - kHeapObjectTag)); | 481 Operand(Code::kHeaderSize - kHeapObjectTag)); |
440 __ Jump(ip); | 482 __ Jump(ip); |
(...skipping 11 matching lines...) Expand all Loading... | |
452 __ cmp(cp, kScratchReg); | 494 __ cmp(cp, kScratchReg); |
453 __ Assert(eq, kWrongFunctionContext); | 495 __ Assert(eq, kWrongFunctionContext); |
454 } | 496 } |
455 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 497 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
456 __ Call(ip); | 498 __ Call(ip); |
457 RecordCallPosition(instr); | 499 RecordCallPosition(instr); |
458 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 500 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
459 frame_access_state()->ClearSPDelta(); | 501 frame_access_state()->ClearSPDelta(); |
460 break; | 502 break; |
461 } | 503 } |
504 case kArchTailCallJSFunctionFromJSFunction: { | |
505 Register func = i.InputRegister(0); | |
506 if (FLAG_debug_code) { | |
507 // Check the function's context matches the context argument. | |
508 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | |
509 __ cmp(cp, kScratchReg); | |
510 __ Assert(eq, kWrongFunctionContext); | |
511 } | |
512 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
513 AssembleDeconstructActivationRecord(stack_param_delta); | |
514 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | |
515 i.TempRegister(0), i.TempRegister(1), | |
516 i.TempRegister(2)); | |
517 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | |
518 __ Jump(ip); | |
519 DCHECK_EQ(LeaveCC, i.OutputSBit()); | |
520 frame_access_state()->ClearSPDelta(); | |
521 break; | |
522 } | |
462 case kArchTailCallJSFunction: { | 523 case kArchTailCallJSFunction: { |
463 Register func = i.InputRegister(0); | 524 Register func = i.InputRegister(0); |
464 if (FLAG_debug_code) { | 525 if (FLAG_debug_code) { |
465 // Check the function's context matches the context argument. | 526 // Check the function's context matches the context argument. |
466 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 527 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
467 __ cmp(cp, kScratchReg); | 528 __ cmp(cp, kScratchReg); |
468 __ Assert(eq, kWrongFunctionContext); | 529 __ Assert(eq, kWrongFunctionContext); |
469 } | 530 } |
470 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 531 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
471 AssembleDeconstructActivationRecord(stack_param_delta); | 532 AssembleDeconstructActivationRecord(stack_param_delta); |
(...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1472 padding_size -= v8::internal::Assembler::kInstrSize; | 1533 padding_size -= v8::internal::Assembler::kInstrSize; |
1473 } | 1534 } |
1474 } | 1535 } |
1475 } | 1536 } |
1476 | 1537 |
1477 #undef __ | 1538 #undef __ |
1478 | 1539 |
1479 } // namespace compiler | 1540 } // namespace compiler |
1480 } // namespace internal | 1541 } // namespace internal |
1481 } // namespace v8 | 1542 } // namespace v8 |
OLD | NEW |