Chromium Code Reviews| 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 |