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