blob: d03f4b60b0e8c87f27745ebcd6f77613ad7ab556 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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.
71enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
72
73// Types of uncatchable exceptions.
74enum 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
89namespace v8 {
90namespace internal {
91
92
93// Code generation can be nested. Code generation scopes form a stack
94// of active code generators.
95class CodeGeneratorScope BASE_EMBEDDED {
96 public:
97 explicit CodeGeneratorScope(CodeGenerator* cgen) {
98 previous_ = top_;
99 top_ = cgen;
100 }
101
102 ~CodeGeneratorScope() {
103 top_ = previous_;
104 }
105
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.
120class DeferredCode: public ZoneObject {
121 public:
122 DeferredCode();
123 virtual ~DeferredCode() { }
124
125 virtual void Generate() = 0;
126
127 MacroAssembler* masm() { return masm_; }
128
129 int statement_position() const { return statement_position_; }
130 int position() const { return position_; }
131
132 Label* entry_label() { return &entry_label_; }
133 Label* exit_label() { return &exit_label_; }
134
135#ifdef DEBUG
136 void set_comment(const char* comment) { comment_ = comment; }
137 const char* comment() const { return comment_; }
138#else
139 void set_comment(const char* comment) { }
140 const char* comment() const { return ""; }
141#endif
142
143 inline void Jump();
144 inline void Branch(Condition cc);
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.
180class RuntimeStub : public CodeStub {
181 public:
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.
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
200 Major MajorKey() { return Runtime; }
201 int MinorKey() {
202 return IdField::encode(id_) | ArgumentField::encode(num_arguments_);
203 }
204
205 const char* GetName();
206
207#ifdef DEBUG
208 void Print() {
209 PrintF("RuntimeStub (id %s)\n", Runtime::FunctionForId(id_)->name);
210 }
211#endif
212};
213
214
215class StackCheckStub : public CodeStub {
216 public:
217 StackCheckStub() { }
218
219 void Generate(MacroAssembler* masm);
220
221 private:
222
223 const char* GetName() { return "StackCheckStub"; }
224
225 Major MajorKey() { return StackCheck; }
226 int MinorKey() { return 0; }
227};
228
229
230class InstanceofStub: public CodeStub {
231 public:
232 InstanceofStub() { }
233
234 void Generate(MacroAssembler* masm);
235
236 private:
237 Major MajorKey() { return Instanceof; }
238 int MinorKey() { return 0; }
239};
240
241
242class UnarySubStub : public CodeStub {
243 public:
244 explicit UnarySubStub(bool overwrite)
245 : overwrite_(overwrite) { }
246
247 private:
248 bool overwrite_;
249 Major MajorKey() { return UnarySub; }
250 int MinorKey() { return overwrite_ ? 1 : 0; }
251 void Generate(MacroAssembler* masm);
252
253 const char* GetName() { return "UnarySubStub"; }
254};
255
256
257class CompareStub: public CodeStub {
258 public:
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
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
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
287class CEntryStub : public CodeStub {
288 public:
289 explicit CEntryStub(int result_size) : result_size_(result_size) { }
290
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 private:
306 // Number of pointers/values returned.
307 int result_size_;
308
309 Major MajorKey() { return CEntry; }
310 // Minor key must differ if different result_size_ values means different
311 // code is generated.
312 int MinorKey();
313
314 const char* GetName() { return "CEntryStub"; }
315};
316
317
318class CEntryDebugBreakStub : public CEntryStub {
319 public:
320 CEntryDebugBreakStub() : CEntryStub(1) { }
321
322 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
323
324 private:
325 int MinorKey() { return 1; }
326
327 const char* GetName() { return "CEntryDebugBreakStub"; }
328};
329
330
331class JSEntryStub : public CodeStub {
332 public:
333 JSEntryStub() { }
334
335 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
336
337 protected:
338 void GenerateBody(MacroAssembler* masm, bool is_construct);
339
340 private:
341 Major MajorKey() { return JSEntry; }
342 int MinorKey() { return 0; }
343
344 const char* GetName() { return "JSEntryStub"; }
345};
346
347
348class JSConstructEntryStub : public JSEntryStub {
349 public:
350 JSConstructEntryStub() { }
351
352 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
353
354 private:
355 int MinorKey() { return 1; }
356
357 const char* GetName() { return "JSConstructEntryStub"; }
358};
359
360
361class ArgumentsAccessStub: public CodeStub {
362 public:
363 enum Type {
364 READ_LENGTH,
365 READ_ELEMENT,
366 NEW_OBJECT
367 };
368
369 explicit ArgumentsAccessStub(Type type) : type_(type) { }
370
371 private:
372 Type type_;
373
374 Major MajorKey() { return ArgumentsAccess; }
375 int MinorKey() { return type_; }
376
377 void Generate(MacroAssembler* masm);
378 void GenerateReadLength(MacroAssembler* masm);
379 void GenerateReadElement(MacroAssembler* masm);
380 void GenerateNewObject(MacroAssembler* masm);
381
382 const char* GetName() { return "ArgumentsAccessStub"; }
383
384#ifdef DEBUG
385 void Print() {
386 PrintF("ArgumentsAccessStub (type %d)\n", type_);
387 }
388#endif
389};
390
391
392} // namespace internal
393} // namespace v8
394
395#endif // V8_CODEGEN_H_