• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_CODEGEN_H_
29 #define V8_CODEGEN_H_
30 
31 #include "ast.h"
32 #include "code-stubs.h"
33 #include "runtime.h"
34 
35 // Include the declaration of the architecture defined class CodeGenerator.
36 // The contract  to the shared code is that the the CodeGenerator is a subclass
37 // of Visitor and that the following methods are available publicly:
38 //   MakeCode
39 //   SetFunctionInfo
40 //   masm
41 //   frame
42 //   has_valid_frame
43 //   SetFrame
44 //   DeleteFrame
45 //   allocator
46 //   AddDeferred
47 //   in_spilled_code
48 //   set_in_spilled_code
49 //
50 // These methods are either used privately by the shared code or implemented as
51 // shared code:
52 //   CodeGenerator
53 //   ~CodeGenerator
54 //   ProcessDeferred
55 //   GenCode
56 //   BuildBoilerplate
57 //   ComputeCallInitialize
58 //   ComputeCallInitializeInLoop
59 //   ProcessDeclarations
60 //   DeclareGlobals
61 //   FindInlineRuntimeLUT
62 //   CheckForInlineRuntimeCall
63 //   PatchInlineRuntimeEntry
64 //   CodeForFunctionPosition
65 //   CodeForReturnPosition
66 //   CodeForStatementPosition
67 //   CodeForSourcePosition
68 
69 
70 // Mode to overwrite BinaryExpression values.
71 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
72 
73 // Types of uncatchable exceptions.
74 enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION };
75 
76 
77 #if V8_TARGET_ARCH_IA32
78 #include "ia32/codegen-ia32.h"
79 #elif V8_TARGET_ARCH_X64
80 #include "x64/codegen-x64.h"
81 #elif V8_TARGET_ARCH_ARM
82 #include "arm/codegen-arm.h"
83 #else
84 #error Unsupported target architecture.
85 #endif
86 
87 #include "register-allocator.h"
88 
89 namespace v8 {
90 namespace internal {
91 
92 
93 // Code generation can be nested.  Code generation scopes form a stack
94 // of active code generators.
95 class CodeGeneratorScope BASE_EMBEDDED {
96  public:
CodeGeneratorScope(CodeGenerator * cgen)97   explicit CodeGeneratorScope(CodeGenerator* cgen) {
98     previous_ = top_;
99     top_ = cgen;
100   }
101 
~CodeGeneratorScope()102   ~CodeGeneratorScope() {
103     top_ = previous_;
104   }
105 
Current()106   static CodeGenerator* Current() {
107     ASSERT(top_ != NULL);
108     return top_;
109   }
110 
111  private:
112   static CodeGenerator* top_;
113   CodeGenerator* previous_;
114 };
115 
116 
117 // Deferred code objects are small pieces of code that are compiled
118 // out of line. They are used to defer the compilation of uncommon
119 // paths thereby avoiding expensive jumps around uncommon code parts.
120 class DeferredCode: public ZoneObject {
121  public:
122   DeferredCode();
~DeferredCode()123   virtual ~DeferredCode() { }
124 
125   virtual void Generate() = 0;
126 
masm()127   MacroAssembler* masm() { return masm_; }
128 
statement_position()129   int statement_position() const { return statement_position_; }
position()130   int position() const { return position_; }
131 
entry_label()132   Label* entry_label() { return &entry_label_; }
exit_label()133   Label* exit_label() { return &exit_label_; }
134 
135 #ifdef DEBUG
set_comment(const char * comment)136   void set_comment(const char* comment) { comment_ = comment; }
comment()137   const char* comment() const { return comment_; }
138 #else
set_comment(const char * comment)139   void set_comment(const char* comment) { }
comment()140   const char* comment() const { return ""; }
141 #endif
142 
143   inline void Jump();
144   inline void Branch(Condition cc);
BindExit()145   void BindExit() { masm_->bind(&exit_label_); }
146 
147   void SaveRegisters();
148   void RestoreRegisters();
149 
150  protected:
151   MacroAssembler* masm_;
152 
153  private:
154   // Constants indicating special actions.  They should not be multiples
155   // of kPointerSize so they will not collide with valid offsets from
156   // the frame pointer.
157   static const int kIgnore = -1;
158   static const int kPush = 1;
159 
160   // This flag is ored with a valid offset from the frame pointer, so
161   // it should fit in the low zero bits of a valid offset.
162   static const int kSyncedFlag = 2;
163 
164   int statement_position_;
165   int position_;
166 
167   Label entry_label_;
168   Label exit_label_;
169 
170   int registers_[RegisterAllocator::kNumRegisters];
171 
172 #ifdef DEBUG
173   const char* comment_;
174 #endif
175   DISALLOW_COPY_AND_ASSIGN(DeferredCode);
176 };
177 
178 
179 // RuntimeStub models code stubs calling entry points in the Runtime class.
180 class RuntimeStub : public CodeStub {
181  public:
RuntimeStub(Runtime::FunctionId id,int num_arguments)182   explicit RuntimeStub(Runtime::FunctionId id, int num_arguments)
183       : id_(id), num_arguments_(num_arguments) { }
184 
185   void Generate(MacroAssembler* masm);
186 
187   // Disassembler support.  It is useful to be able to print the name
188   // of the runtime function called through this stub.
GetNameFromMinorKey(int minor_key)189   static const char* GetNameFromMinorKey(int minor_key) {
190     return Runtime::FunctionForId(IdField::decode(minor_key))->stub_name;
191   }
192 
193  private:
194   Runtime::FunctionId id_;
195   int num_arguments_;
196 
197   class ArgumentField: public BitField<int,  0, 16> {};
198   class IdField: public BitField<Runtime::FunctionId, 16, kMinorBits - 16> {};
199 
MajorKey()200   Major MajorKey() { return Runtime; }
MinorKey()201   int MinorKey() {
202     return IdField::encode(id_) | ArgumentField::encode(num_arguments_);
203   }
204 
205   const char* GetName();
206 
207 #ifdef DEBUG
Print()208   void Print() {
209     PrintF("RuntimeStub (id %s)\n", Runtime::FunctionForId(id_)->name);
210   }
211 #endif
212 };
213 
214 
215 class StackCheckStub : public CodeStub {
216  public:
StackCheckStub()217   StackCheckStub() { }
218 
219   void Generate(MacroAssembler* masm);
220 
221  private:
222 
GetName()223   const char* GetName() { return "StackCheckStub"; }
224 
MajorKey()225   Major MajorKey() { return StackCheck; }
MinorKey()226   int MinorKey() { return 0; }
227 };
228 
229 
230 class InstanceofStub: public CodeStub {
231  public:
InstanceofStub()232   InstanceofStub() { }
233 
234   void Generate(MacroAssembler* masm);
235 
236  private:
MajorKey()237   Major MajorKey() { return Instanceof; }
MinorKey()238   int MinorKey() { return 0; }
239 };
240 
241 
242 class UnarySubStub : public CodeStub {
243  public:
UnarySubStub(bool overwrite)244   explicit UnarySubStub(bool overwrite)
245       : overwrite_(overwrite) { }
246 
247  private:
248   bool overwrite_;
MajorKey()249   Major MajorKey() { return UnarySub; }
MinorKey()250   int MinorKey() { return overwrite_ ? 1 : 0; }
251   void Generate(MacroAssembler* masm);
252 
GetName()253   const char* GetName() { return "UnarySubStub"; }
254 };
255 
256 
257 class CompareStub: public CodeStub {
258  public:
CompareStub(Condition cc,bool strict)259   CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { }
260 
261   void Generate(MacroAssembler* masm);
262 
263  private:
264   Condition cc_;
265   bool strict_;
266 
MajorKey()267   Major MajorKey() { return Compare; }
268 
269   int MinorKey();
270 
271   // Branch to the label if the given object isn't a symbol.
272   void BranchIfNonSymbol(MacroAssembler* masm,
273                          Label* label,
274                          Register object,
275                          Register scratch);
276 
277 #ifdef DEBUG
Print()278   void Print() {
279     PrintF("CompareStub (cc %d), (strict %s)\n",
280            static_cast<int>(cc_),
281            strict_ ? "true" : "false");
282   }
283 #endif
284 };
285 
286 
287 class CEntryStub : public CodeStub {
288  public:
CEntryStub()289   CEntryStub() { }
290 
Generate(MacroAssembler * masm)291   void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
292 
293  protected:
294   void GenerateBody(MacroAssembler* masm, bool is_debug_break);
295   void GenerateCore(MacroAssembler* masm,
296                     Label* throw_normal_exception,
297                     Label* throw_termination_exception,
298                     Label* throw_out_of_memory_exception,
299                     StackFrame::Type frame_type,
300                     bool do_gc,
301                     bool always_allocate_scope);
302   void GenerateThrowTOS(MacroAssembler* masm);
303   void GenerateThrowUncatchable(MacroAssembler* masm,
304                                 UncatchableExceptionType type);
305 
306  private:
MajorKey()307   Major MajorKey() { return CEntry; }
MinorKey()308   int MinorKey() { return 0; }
309 
GetName()310   const char* GetName() { return "CEntryStub"; }
311 };
312 
313 
314 class CEntryDebugBreakStub : public CEntryStub {
315  public:
CEntryDebugBreakStub()316   CEntryDebugBreakStub() { }
317 
Generate(MacroAssembler * masm)318   void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
319 
320  private:
MinorKey()321   int MinorKey() { return 1; }
322 
GetName()323   const char* GetName() { return "CEntryDebugBreakStub"; }
324 };
325 
326 
327 class JSEntryStub : public CodeStub {
328  public:
JSEntryStub()329   JSEntryStub() { }
330 
Generate(MacroAssembler * masm)331   void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
332 
333  protected:
334   void GenerateBody(MacroAssembler* masm, bool is_construct);
335 
336  private:
MajorKey()337   Major MajorKey() { return JSEntry; }
MinorKey()338   int MinorKey() { return 0; }
339 
GetName()340   const char* GetName() { return "JSEntryStub"; }
341 };
342 
343 
344 class JSConstructEntryStub : public JSEntryStub {
345  public:
JSConstructEntryStub()346   JSConstructEntryStub() { }
347 
Generate(MacroAssembler * masm)348   void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
349 
350  private:
MinorKey()351   int MinorKey() { return 1; }
352 
GetName()353   const char* GetName() { return "JSConstructEntryStub"; }
354 };
355 
356 
357 class ArgumentsAccessStub: public CodeStub {
358  public:
359   enum Type {
360     READ_LENGTH,
361     READ_ELEMENT,
362     NEW_OBJECT
363   };
364 
ArgumentsAccessStub(Type type)365   explicit ArgumentsAccessStub(Type type) : type_(type) { }
366 
367  private:
368   Type type_;
369 
MajorKey()370   Major MajorKey() { return ArgumentsAccess; }
MinorKey()371   int MinorKey() { return type_; }
372 
373   void Generate(MacroAssembler* masm);
374   void GenerateReadLength(MacroAssembler* masm);
375   void GenerateReadElement(MacroAssembler* masm);
376   void GenerateNewObject(MacroAssembler* masm);
377 
GetName()378   const char* GetName() { return "ArgumentsAccessStub"; }
379 
380 #ifdef DEBUG
Print()381   void Print() {
382     PrintF("ArgumentsAccessStub (type %d)\n", type_);
383   }
384 #endif
385 };
386 
387 
388 }  // namespace internal
389 }  // namespace v8
390 
391 #endif  // V8_CODEGEN_H_
392