codegen.h revision d0582a6c46733687d045e4188a1bcd0123c758a1
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//   MakeCodePrologue
40//   MakeCodeEpilogue
41//   masm
42//   frame
43//   script
44//   has_valid_frame
45//   SetFrame
46//   DeleteFrame
47//   allocator
48//   AddDeferred
49//   in_spilled_code
50//   set_in_spilled_code
51//   RecordPositions
52//
53// These methods are either used privately by the shared code or implemented as
54// shared code:
55//   CodeGenerator
56//   ~CodeGenerator
57//   ProcessDeferred
58//   GenCode
59//   ComputeLazyCompile
60//   BuildBoilerplate
61//   ComputeCallInitialize
62//   ComputeCallInitializeInLoop
63//   ProcessDeclarations
64//   DeclareGlobals
65//   FindInlineRuntimeLUT
66//   CheckForInlineRuntimeCall
67//   PatchInlineRuntimeEntry
68//   AnalyzeCondition
69//   CodeForFunctionPosition
70//   CodeForReturnPosition
71//   CodeForStatementPosition
72//   CodeForDoWhileConditionPosition
73//   CodeForSourcePosition
74
75
76// Mode to overwrite BinaryExpression values.
77enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
78
79// Types of uncatchable exceptions.
80enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION };
81
82
83#if V8_TARGET_ARCH_IA32
84#include "ia32/codegen-ia32.h"
85#elif V8_TARGET_ARCH_X64
86#include "x64/codegen-x64.h"
87#elif V8_TARGET_ARCH_ARM
88#include "arm/codegen-arm.h"
89#else
90#error Unsupported target architecture.
91#endif
92
93#include "register-allocator.h"
94
95namespace v8 {
96namespace internal {
97
98
99// Code generation can be nested.  Code generation scopes form a stack
100// of active code generators.
101class CodeGeneratorScope BASE_EMBEDDED {
102 public:
103  explicit CodeGeneratorScope(CodeGenerator* cgen) {
104    previous_ = top_;
105    top_ = cgen;
106  }
107
108  ~CodeGeneratorScope() {
109    top_ = previous_;
110  }
111
112  static CodeGenerator* Current() {
113    ASSERT(top_ != NULL);
114    return top_;
115  }
116
117 private:
118  static CodeGenerator* top_;
119  CodeGenerator* previous_;
120};
121
122
123// Deferred code objects are small pieces of code that are compiled
124// out of line. They are used to defer the compilation of uncommon
125// paths thereby avoiding expensive jumps around uncommon code parts.
126class DeferredCode: public ZoneObject {
127 public:
128  DeferredCode();
129  virtual ~DeferredCode() { }
130
131  virtual void Generate() = 0;
132
133  MacroAssembler* masm() { return masm_; }
134
135  int statement_position() const { return statement_position_; }
136  int position() const { return position_; }
137
138  Label* entry_label() { return &entry_label_; }
139  Label* exit_label() { return &exit_label_; }
140
141#ifdef DEBUG
142  void set_comment(const char* comment) { comment_ = comment; }
143  const char* comment() const { return comment_; }
144#else
145  void set_comment(const char* comment) { }
146  const char* comment() const { return ""; }
147#endif
148
149  inline void Jump();
150  inline void Branch(Condition cc);
151  void BindExit() { masm_->bind(&exit_label_); }
152
153  void SaveRegisters();
154  void RestoreRegisters();
155
156 protected:
157  MacroAssembler* masm_;
158
159 private:
160  // Constants indicating special actions.  They should not be multiples
161  // of kPointerSize so they will not collide with valid offsets from
162  // the frame pointer.
163  static const int kIgnore = -1;
164  static const int kPush = 1;
165
166  // This flag is ored with a valid offset from the frame pointer, so
167  // it should fit in the low zero bits of a valid offset.
168  static const int kSyncedFlag = 2;
169
170  int statement_position_;
171  int position_;
172
173  Label entry_label_;
174  Label exit_label_;
175
176  int registers_[RegisterAllocator::kNumRegisters];
177
178#ifdef DEBUG
179  const char* comment_;
180#endif
181  DISALLOW_COPY_AND_ASSIGN(DeferredCode);
182};
183
184
185// RuntimeStub models code stubs calling entry points in the Runtime class.
186class RuntimeStub : public CodeStub {
187 public:
188  explicit RuntimeStub(Runtime::FunctionId id, int num_arguments)
189      : id_(id), num_arguments_(num_arguments) { }
190
191  void Generate(MacroAssembler* masm);
192
193  // Disassembler support.  It is useful to be able to print the name
194  // of the runtime function called through this stub.
195  static const char* GetNameFromMinorKey(int minor_key) {
196    return Runtime::FunctionForId(IdField::decode(minor_key))->stub_name;
197  }
198
199 private:
200  Runtime::FunctionId id_;
201  int num_arguments_;
202
203  class ArgumentField: public BitField<int,  0, 16> {};
204  class IdField: public BitField<Runtime::FunctionId, 16, kMinorBits - 16> {};
205
206  Major MajorKey() { return Runtime; }
207  int MinorKey() {
208    return IdField::encode(id_) | ArgumentField::encode(num_arguments_);
209  }
210
211  const char* GetName();
212
213#ifdef DEBUG
214  void Print() {
215    PrintF("RuntimeStub (id %s)\n", Runtime::FunctionForId(id_)->name);
216  }
217#endif
218};
219
220
221class StackCheckStub : public CodeStub {
222 public:
223  StackCheckStub() { }
224
225  void Generate(MacroAssembler* masm);
226
227 private:
228
229  const char* GetName() { return "StackCheckStub"; }
230
231  Major MajorKey() { return StackCheck; }
232  int MinorKey() { return 0; }
233};
234
235
236class InstanceofStub: public CodeStub {
237 public:
238  InstanceofStub() { }
239
240  void Generate(MacroAssembler* masm);
241
242 private:
243  Major MajorKey() { return Instanceof; }
244  int MinorKey() { return 0; }
245};
246
247
248class UnarySubStub : public CodeStub {
249 public:
250  explicit UnarySubStub(bool overwrite)
251      : overwrite_(overwrite) { }
252
253 private:
254  bool overwrite_;
255  Major MajorKey() { return UnarySub; }
256  int MinorKey() { return overwrite_ ? 1 : 0; }
257  void Generate(MacroAssembler* masm);
258
259  const char* GetName() { return "UnarySubStub"; }
260};
261
262
263class CompareStub: public CodeStub {
264 public:
265  CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { }
266
267  void Generate(MacroAssembler* masm);
268
269 private:
270  Condition cc_;
271  bool strict_;
272
273  Major MajorKey() { return Compare; }
274
275  int MinorKey();
276
277  // Branch to the label if the given object isn't a symbol.
278  void BranchIfNonSymbol(MacroAssembler* masm,
279                         Label* label,
280                         Register object,
281                         Register scratch);
282
283#ifdef DEBUG
284  void Print() {
285    PrintF("CompareStub (cc %d), (strict %s)\n",
286           static_cast<int>(cc_),
287           strict_ ? "true" : "false");
288  }
289#endif
290};
291
292
293class CEntryStub : public CodeStub {
294 public:
295  explicit CEntryStub(int result_size) : result_size_(result_size) { }
296
297  void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
298
299 protected:
300  void GenerateBody(MacroAssembler* masm, bool is_debug_break);
301  void GenerateCore(MacroAssembler* masm,
302                    Label* throw_normal_exception,
303                    Label* throw_termination_exception,
304                    Label* throw_out_of_memory_exception,
305                    ExitFrame::Mode mode,
306                    bool do_gc,
307                    bool always_allocate_scope);
308  void GenerateThrowTOS(MacroAssembler* masm);
309  void GenerateThrowUncatchable(MacroAssembler* masm,
310                                UncatchableExceptionType type);
311 private:
312  // Number of pointers/values returned.
313  int result_size_;
314
315  Major MajorKey() { return CEntry; }
316  // Minor key must differ if different result_size_ values means different
317  // code is generated.
318  int MinorKey();
319
320  const char* GetName() { return "CEntryStub"; }
321};
322
323
324class ApiGetterEntryStub : public CodeStub {
325 public:
326  ApiGetterEntryStub(Handle<AccessorInfo> info,
327                     ApiFunction* fun)
328      : info_(info),
329        fun_(fun) { }
330  void Generate(MacroAssembler* masm);
331  virtual bool has_custom_cache() { return true; }
332  virtual bool GetCustomCache(Code** code_out);
333  virtual void SetCustomCache(Code* value);
334
335  static const int kStackSpace = 6;
336  static const int kArgc = 4;
337 private:
338  Handle<AccessorInfo> info() { return info_; }
339  ApiFunction* fun() { return fun_; }
340  Major MajorKey() { return NoCache; }
341  int MinorKey() { return 0; }
342  const char* GetName() { return "ApiEntryStub"; }
343  // The accessor info associated with the function.
344  Handle<AccessorInfo> info_;
345  // The function to be called.
346  ApiFunction* fun_;
347};
348
349
350class CEntryDebugBreakStub : public CEntryStub {
351 public:
352  CEntryDebugBreakStub() : CEntryStub(1) { }
353
354  void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
355
356 private:
357  int MinorKey() { return 1; }
358
359  const char* GetName() { return "CEntryDebugBreakStub"; }
360};
361
362
363class JSEntryStub : public CodeStub {
364 public:
365  JSEntryStub() { }
366
367  void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
368
369 protected:
370  void GenerateBody(MacroAssembler* masm, bool is_construct);
371
372 private:
373  Major MajorKey() { return JSEntry; }
374  int MinorKey() { return 0; }
375
376  const char* GetName() { return "JSEntryStub"; }
377};
378
379
380class JSConstructEntryStub : public JSEntryStub {
381 public:
382  JSConstructEntryStub() { }
383
384  void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
385
386 private:
387  int MinorKey() { return 1; }
388
389  const char* GetName() { return "JSConstructEntryStub"; }
390};
391
392
393class ArgumentsAccessStub: public CodeStub {
394 public:
395  enum Type {
396    READ_LENGTH,
397    READ_ELEMENT,
398    NEW_OBJECT
399  };
400
401  explicit ArgumentsAccessStub(Type type) : type_(type) { }
402
403 private:
404  Type type_;
405
406  Major MajorKey() { return ArgumentsAccess; }
407  int MinorKey() { return type_; }
408
409  void Generate(MacroAssembler* masm);
410  void GenerateReadLength(MacroAssembler* masm);
411  void GenerateReadElement(MacroAssembler* masm);
412  void GenerateNewObject(MacroAssembler* masm);
413
414  const char* GetName() { return "ArgumentsAccessStub"; }
415
416#ifdef DEBUG
417  void Print() {
418    PrintF("ArgumentsAccessStub (type %d)\n", type_);
419  }
420#endif
421};
422
423
424}  // namespace internal
425}  // namespace v8
426
427#endif  // V8_CODEGEN_H_
428