blob: 85a08d59e55ea7a0f77689e93ec3c76c9781a5fc [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// masm
42// frame
Steve Blockd0582a62009-12-15 09:54:21 +000043// script
Steve Blocka7e24c12009-10-30 11:49:00 +000044// 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
Steve Blockd0582a62009-12-15 09:54:21 +000072// CodeForDoWhileConditionPosition
Steve Blocka7e24c12009-10-30 11:49:00 +000073// 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,
Steve Blockd0582a62009-12-15 09:54:21 +0000305 ExitFrame::Mode mode,
Steve Blocka7e24c12009-10-30 11:49:00 +0000306 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
Steve Blockd0582a62009-12-15 09:54:21 +0000324class 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
Steve Blocka7e24c12009-10-30 11:49:00 +0000350class 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_