| // Copyright 2009 the V8 project authors. All rights reserved. |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer in the documentation and/or other materials provided |
| // with the distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| |
| #include "v8.h" |
| #include "macro-assembler.h" |
| #include "register-allocator-inl.h" |
| #include "codegen.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| // ------------------------------------------------------------------------- |
| // Platform-specific DeferredCode functions. |
| |
| void DeferredCode::SaveRegisters() { UNIMPLEMENTED(); } |
| |
| void DeferredCode::RestoreRegisters() { UNIMPLEMENTED(); } |
| |
| |
| CodeGenerator::CodeGenerator(int buffer_size, |
| Handle<Script> script, |
| bool is_eval) |
| : is_eval_(is_eval), |
| script_(script), |
| deferred_(8), |
| masm_(new MacroAssembler(NULL, buffer_size)), |
| scope_(NULL), |
| frame_(NULL), |
| allocator_(NULL), |
| state_(NULL), |
| loop_nesting_(0), |
| function_return_is_shadowed_(false), |
| in_spilled_code_(false) { |
| } |
| |
| #define __ masm-> |
| |
| |
| void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::GenCode(FunctionLiteral* a) { |
| masm_->int3(); // UNIMPLEMENTED |
| } |
| |
| void CodeGenerator::GenerateFastCaseSwitchJumpTable(SwitchStatement* a, |
| int b, |
| int c, |
| Label* d, |
| Vector<Label*> e, |
| Vector<Label> f) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitStatements(ZoneList<Statement*>* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitBlock(Block* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitDeclaration(Declaration* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitExpressionStatement(ExpressionStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitEmptyStatement(EmptyStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitIfStatement(IfStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitContinueStatement(ContinueStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitBreakStatement(BreakStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitReturnStatement(ReturnStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitWithExitStatement(WithExitStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitSwitchStatement(SwitchStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitLoopStatement(LoopStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitForInStatement(ForInStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitTryCatch(TryCatch* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitTryFinally(TryFinally* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitFunctionBoilerplateLiteral( |
| FunctionBoilerplateLiteral* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitConditional(Conditional* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitSlot(Slot* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitVariableProxy(VariableProxy* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitLiteral(Literal* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitObjectLiteral(ObjectLiteral* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitArrayLiteral(ArrayLiteral* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitAssignment(Assignment* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitThrow(Throw* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitProperty(Property* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitCall(Call* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitCallEval(CallEval* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitCallNew(CallNew* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitCallRuntime(CallRuntime* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitUnaryOperation(UnaryOperation* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitCountOperation(CountOperation* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitBinaryOperation(BinaryOperation* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitCompareOperation(CompareOperation* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| void CodeGenerator::VisitThisFunction(ThisFunction* a) { |
| UNIMPLEMENTED(); |
| } |
| |
| |
| void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { |
| masm->int3(); // TODO(X64): UNIMPLEMENTED. |
| } |
| |
| |
| void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
| Label invoke, exit; |
| |
| // Setup frame. |
| __ push(rbp); |
| __ movq(rbp, rsp); |
| |
| // Save callee-saved registers (X64 calling conventions). |
| int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
| // Push something that is not an arguments adaptor. |
| __ push(Immediate(ArgumentsAdaptorFrame::NON_SENTINEL)); |
| __ push(Immediate(Smi::FromInt(marker))); // @ function offset |
| __ push(r12); |
| __ push(r13); |
| __ push(r14); |
| __ push(r15); |
| __ push(rdi); |
| __ push(rsi); |
| __ push(rbx); |
| // TODO(X64): Push XMM6-XMM15 (low 64 bits) as well, or make them |
| // callee-save in JS code as well. |
| |
| // Save copies of the top frame descriptor on the stack. |
| ExternalReference c_entry_fp(Top::k_c_entry_fp_address); |
| __ load_rax(c_entry_fp); |
| __ push(rax); |
| |
| // Call a faked try-block that does the invoke. |
| __ call(&invoke); |
| |
| // Caught exception: Store result (exception) in the pending |
| // exception field in the JSEnv and return a failure sentinel. |
| ExternalReference pending_exception(Top::k_pending_exception_address); |
| __ store_rax(pending_exception); |
| __ movq(rax, Failure::Exception(), RelocInfo::NONE); |
| __ jmp(&exit); |
| |
| // Invoke: Link this frame into the handler chain. |
| __ bind(&invoke); |
| __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); |
| __ push(rax); // flush TOS |
| |
| // Clear any pending exceptions. |
| __ load_rax(ExternalReference::the_hole_value_location()); |
| __ store_rax(pending_exception); |
| |
| // Fake a receiver (NULL). |
| __ push(Immediate(0)); // receiver |
| |
| // Invoke the function by calling through JS entry trampoline |
| // builtin and pop the faked function when we return. We load the address |
| // from an external reference instead of inlining the call target address |
| // directly in the code, because the builtin stubs may not have been |
| // generated yet at the time this code is generated. |
| if (is_construct) { |
| ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); |
| __ load_rax(construct_entry); |
| } else { |
| ExternalReference entry(Builtins::JSEntryTrampoline); |
| __ load_rax(entry); |
| } |
| __ call(FieldOperand(rax, Code::kHeaderSize)); |
| |
| // Unlink this frame from the handler chain. |
| __ movq(kScratchRegister, ExternalReference(Top::k_handler_address)); |
| __ pop(Operand(kScratchRegister, 0)); |
| // Pop next_sp. |
| __ add(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); |
| |
| // Restore the top frame descriptor from the stack. |
| __ bind(&exit); |
| __ movq(kScratchRegister, ExternalReference(Top::k_c_entry_fp_address)); |
| __ pop(Operand(kScratchRegister, 0)); |
| |
| // Restore callee-saved registers (X64 conventions). |
| __ pop(rbx); |
| __ pop(rsi); |
| __ pop(rdi); |
| __ pop(r15); |
| __ pop(r14); |
| __ pop(r13); |
| __ pop(r12); |
| __ add(rsp, Immediate(2 * kPointerSize)); // remove markers |
| |
| // Restore frame pointer and return. |
| __ pop(rbp); |
| __ ret(0); |
| } |
| |
| |
| #undef __ |
| |
| } } // namespace v8::internal |