2010-09-14 14:52:53 +00:00
|
|
|
// Copyright 2010 the V8 project authors. All rights reserved.
|
2008-07-03 15:10:15 +00:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
#ifndef V8_CODEGEN_H_
|
2008-10-10 00:00:52 +00:00
|
|
|
#define V8_CODEGEN_H_
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
#include "code-stubs.h"
|
|
|
|
#include "runtime.h"
|
2010-03-25 12:44:15 +00:00
|
|
|
#include "type-info.h"
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2008-10-10 00:00:52 +00:00
|
|
|
// Include the declaration of the architecture defined class CodeGenerator.
|
|
|
|
// The contract to the shared code is that the the CodeGenerator is a subclass
|
|
|
|
// of Visitor and that the following methods are available publicly:
|
2009-04-02 08:58:18 +00:00
|
|
|
// MakeCode
|
Initial infrastructure for fast compilation of top-level code. The
fast code generator is optimized for compilation time and code size.
Currently it is only implemented on IA32. It is potentially triggered
for any code in the global scope (including code eval'd in the global
scope). It performs a syntactic check and chooses to compile in fast
mode if the AST contains only supported constructs and matches some
other constraints.
Initially supported constructs are
* ExpressionStatement,
* ReturnStatement,
* VariableProxy (variable references) to parameters and
stack-allocated locals,
* Assignment with lhs a parameter or stack-allocated local, and
* Literal
This allows compilation of literals at the top level and not much
else.
All intermediate values are allocated to temporaries and the stack is
used for all temporaries. The extra memory traffic is a known issue.
The code generated for 'true' is:
0 push ebp
1 mov ebp,esp
3 push esi
4 push edi
5 push 0xf5cca135 ;; object: 0xf5cca135 <undefined>
10 cmp esp,[0x8277efc]
16 jnc 27 (0xf5cbbb1b)
22 call 0xf5cac960 ;; code: STUB, StackCheck, minor: 0
27 push 0xf5cca161 ;; object: 0xf5cca161 <true>
32 mov eax,[esp]
35 mov [ebp+0xf4],eax
38 pop eax
39 mov eax,[ebp+0xf4]
42 mov esp,ebp ;; js return
44 pop ebp
45 ret 0x4
48 mov eax,0xf5cca135 ;; object: 0xf5cca135 <undefined>
53 mov esp,ebp ;; js return
55 pop ebp
56 ret 0x4
Review URL: http://codereview.chromium.org/273050
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3067 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2009-10-14 19:30:50 +00:00
|
|
|
// MakeCodePrologue
|
|
|
|
// MakeCodeEpilogue
|
2009-04-02 08:58:18 +00:00
|
|
|
// masm
|
|
|
|
// frame
|
2009-11-04 17:59:24 +00:00
|
|
|
// script
|
2009-04-02 08:58:18 +00:00
|
|
|
// has_valid_frame
|
|
|
|
// SetFrame
|
|
|
|
// DeleteFrame
|
|
|
|
// allocator
|
|
|
|
// AddDeferred
|
|
|
|
// in_spilled_code
|
|
|
|
// set_in_spilled_code
|
2009-10-15 15:27:37 +00:00
|
|
|
// RecordPositions
|
2008-10-10 00:00:52 +00:00
|
|
|
//
|
|
|
|
// These methods are either used privately by the shared code or implemented as
|
|
|
|
// shared code:
|
2009-04-02 08:58:18 +00:00
|
|
|
// CodeGenerator
|
|
|
|
// ~CodeGenerator
|
|
|
|
// ProcessDeferred
|
2010-02-03 07:58:47 +00:00
|
|
|
// Generate
|
2009-10-21 09:17:39 +00:00
|
|
|
// ComputeLazyCompile
|
2010-03-23 06:04:44 +00:00
|
|
|
// BuildFunctionInfo
|
2009-04-02 08:58:18 +00:00
|
|
|
// ProcessDeclarations
|
|
|
|
// DeclareGlobals
|
|
|
|
// CheckForInlineRuntimeCall
|
2009-10-12 13:14:06 +00:00
|
|
|
// AnalyzeCondition
|
2009-04-02 08:58:18 +00:00
|
|
|
// CodeForFunctionPosition
|
|
|
|
// CodeForReturnPosition
|
|
|
|
// CodeForStatementPosition
|
2009-11-16 21:59:31 +00:00
|
|
|
// CodeForDoWhileConditionPosition
|
2009-04-02 08:58:18 +00:00
|
|
|
// CodeForSourcePosition
|
2008-10-10 00:00:52 +00:00
|
|
|
|
2010-12-07 11:31:57 +00:00
|
|
|
enum InitState { CONST_INIT, NOT_CONST_INIT };
|
|
|
|
enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
|
|
|
|
|
2010-08-06 13:04:27 +00:00
|
|
|
#if V8_TARGET_ARCH_IA32
|
|
|
|
#include "ia32/codegen-ia32.h"
|
|
|
|
#elif V8_TARGET_ARCH_X64
|
|
|
|
#include "x64/codegen-x64.h"
|
|
|
|
#elif V8_TARGET_ARCH_ARM
|
|
|
|
#include "arm/codegen-arm.h"
|
|
|
|
#elif V8_TARGET_ARCH_MIPS
|
|
|
|
#include "mips/codegen-mips.h"
|
|
|
|
#else
|
|
|
|
#error Unsupported target architecture.
|
|
|
|
#endif
|
2010-03-11 09:27:12 +00:00
|
|
|
|
2010-08-06 13:04:27 +00:00
|
|
|
#include "register-allocator.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
2010-03-11 09:27:12 +00:00
|
|
|
|
2009-05-15 11:09:51 +00:00
|
|
|
// Code generation can be nested. Code generation scopes form a stack
|
|
|
|
// of active code generators.
|
|
|
|
class CodeGeneratorScope BASE_EMBEDDED {
|
|
|
|
public:
|
|
|
|
explicit CodeGeneratorScope(CodeGenerator* cgen) {
|
|
|
|
previous_ = top_;
|
|
|
|
top_ = cgen;
|
|
|
|
}
|
|
|
|
|
|
|
|
~CodeGeneratorScope() {
|
|
|
|
top_ = previous_;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CodeGenerator* Current() {
|
|
|
|
ASSERT(top_ != NULL);
|
|
|
|
return top_;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static CodeGenerator* top_;
|
|
|
|
CodeGenerator* previous_;
|
|
|
|
};
|
|
|
|
|
2010-08-16 16:06:46 +00:00
|
|
|
|
2010-05-27 13:48:52 +00:00
|
|
|
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
|
|
|
|
|
2010-05-26 14:23:19 +00:00
|
|
|
// State of used registers in a virtual frame.
|
|
|
|
class FrameRegisterState {
|
|
|
|
public:
|
|
|
|
// Captures the current state of the given frame.
|
|
|
|
explicit FrameRegisterState(VirtualFrame* frame);
|
|
|
|
|
|
|
|
// Saves the state in the stack.
|
|
|
|
void Save(MacroAssembler* masm) const;
|
|
|
|
|
|
|
|
// Restores the state from the stack.
|
|
|
|
void Restore(MacroAssembler* masm) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Constants indicating special actions. They should not be multiples
|
|
|
|
// of kPointerSize so they will not collide with valid offsets from
|
|
|
|
// the frame pointer.
|
|
|
|
static const int kIgnore = -1;
|
|
|
|
static const int kPush = 1;
|
|
|
|
|
|
|
|
// This flag is ored with a valid offset from the frame pointer, so
|
|
|
|
// it should fit in the low zero bits of a valid offset.
|
|
|
|
static const int kSyncedFlag = 2;
|
|
|
|
|
2010-05-27 13:48:52 +00:00
|
|
|
int registers_[RegisterAllocator::kNumRegisters];
|
|
|
|
};
|
|
|
|
|
|
|
|
#elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
|
|
|
|
|
|
|
|
|
|
|
|
class FrameRegisterState {
|
|
|
|
public:
|
|
|
|
inline FrameRegisterState(VirtualFrame frame) : frame_(frame) { }
|
|
|
|
|
|
|
|
inline const VirtualFrame* frame() const { return &frame_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
VirtualFrame frame_;
|
2010-05-26 14:23:19 +00:00
|
|
|
};
|
|
|
|
|
2010-05-27 13:48:52 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
#error Unsupported target architecture.
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2010-05-26 14:23:19 +00:00
|
|
|
|
|
|
|
// RuntimeCallHelper implementation that saves/restores state of a
|
|
|
|
// virtual frame.
|
|
|
|
class VirtualFrameRuntimeCallHelper : public RuntimeCallHelper {
|
|
|
|
public:
|
|
|
|
// Does not take ownership of |frame_state|.
|
|
|
|
explicit VirtualFrameRuntimeCallHelper(const FrameRegisterState* frame_state)
|
|
|
|
: frame_state_(frame_state) {}
|
|
|
|
|
|
|
|
virtual void BeforeCall(MacroAssembler* masm) const;
|
|
|
|
|
|
|
|
virtual void AfterCall(MacroAssembler* masm) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
const FrameRegisterState* frame_state_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// Deferred code objects are small pieces of code that are compiled
|
|
|
|
// out of line. They are used to defer the compilation of uncommon
|
|
|
|
// paths thereby avoiding expensive jumps around uncommon code parts.
|
|
|
|
class DeferredCode: public ZoneObject {
|
|
|
|
public:
|
2009-05-27 15:13:00 +00:00
|
|
|
DeferredCode();
|
2008-07-03 15:10:15 +00:00
|
|
|
virtual ~DeferredCode() { }
|
|
|
|
|
|
|
|
virtual void Generate() = 0;
|
|
|
|
|
2009-06-05 14:16:32 +00:00
|
|
|
MacroAssembler* masm() { return masm_; }
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2008-09-18 08:51:43 +00:00
|
|
|
int statement_position() const { return statement_position_; }
|
2008-07-03 15:10:15 +00:00
|
|
|
int position() const { return position_; }
|
|
|
|
|
2009-06-05 14:16:32 +00:00
|
|
|
Label* entry_label() { return &entry_label_; }
|
|
|
|
Label* exit_label() { return &exit_label_; }
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
void set_comment(const char* comment) { comment_ = comment; }
|
|
|
|
const char* comment() const { return comment_; }
|
|
|
|
#else
|
2009-05-27 15:13:00 +00:00
|
|
|
void set_comment(const char* comment) { }
|
2008-07-03 15:10:15 +00:00
|
|
|
const char* comment() const { return ""; }
|
|
|
|
#endif
|
|
|
|
|
2009-06-05 14:16:32 +00:00
|
|
|
inline void Jump();
|
|
|
|
inline void Branch(Condition cc);
|
|
|
|
void BindExit() { masm_->bind(&exit_label_); }
|
|
|
|
|
2010-05-26 14:23:19 +00:00
|
|
|
const FrameRegisterState* frame_state() const { return &frame_state_; }
|
|
|
|
|
2009-06-05 14:16:32 +00:00
|
|
|
void SaveRegisters();
|
|
|
|
void RestoreRegisters();
|
2010-08-09 13:12:02 +00:00
|
|
|
void Exit();
|
|
|
|
|
|
|
|
// If this returns true then all registers will be saved for the duration
|
|
|
|
// of the Generate() call. Otherwise the registers are not saved and the
|
|
|
|
// Generate() call must bracket runtime any runtime calls with calls to
|
|
|
|
// SaveRegisters() and RestoreRegisters(). In this case the Generate
|
|
|
|
// method must also call Exit() in order to return to the non-deferred
|
|
|
|
// code.
|
|
|
|
virtual bool AutoSaveAndRestore() { return true; }
|
2009-06-05 14:16:32 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
protected:
|
2009-06-05 14:16:32 +00:00
|
|
|
MacroAssembler* masm_;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
private:
|
2008-09-18 08:51:43 +00:00
|
|
|
int statement_position_;
|
2008-07-03 15:10:15 +00:00
|
|
|
int position_;
|
2009-06-05 14:16:32 +00:00
|
|
|
|
|
|
|
Label entry_label_;
|
|
|
|
Label exit_label_;
|
|
|
|
|
2010-05-26 14:23:19 +00:00
|
|
|
FrameRegisterState frame_state_;
|
2009-06-05 14:16:32 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
const char* comment_;
|
|
|
|
#endif
|
2008-08-28 09:55:41 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(DeferredCode);
|
2008-07-03 15:10:15 +00:00
|
|
|
};
|
|
|
|
|
2010-05-26 14:23:19 +00:00
|
|
|
|
2010-08-30 11:48:07 +00:00
|
|
|
} } // namespace v8::internal
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
#endif // V8_CODEGEN_H_
|