| 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 |