blob: 00f4c06e29156d76522ab90a434edf5d559aae28 [file] [log] [blame]
Leon Clarkef7060e22010-06-03 12:02:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Leon Clarked91b9f72010-01-27 17:25:45 +00002// 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_FULL_CODEGEN_H_
29#define V8_FULL_CODEGEN_H_
30
31#include "v8.h"
32
33#include "ast.h"
Leon Clarkef7060e22010-06-03 12:02:55 +010034#include "compiler.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000035
36namespace v8 {
37namespace internal {
38
39class FullCodeGenSyntaxChecker: public AstVisitor {
40 public:
41 FullCodeGenSyntaxChecker() : has_supported_syntax_(true) {}
42
43 void Check(FunctionLiteral* fun);
44
45 bool has_supported_syntax() { return has_supported_syntax_; }
46
47 private:
48 void VisitDeclarations(ZoneList<Declaration*>* decls);
49 void VisitStatements(ZoneList<Statement*>* stmts);
50
51 // AST node visit functions.
52#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
53 AST_NODE_LIST(DECLARE_VISIT)
54#undef DECLARE_VISIT
55
56 bool has_supported_syntax_;
57
58 DISALLOW_COPY_AND_ASSIGN(FullCodeGenSyntaxChecker);
59};
60
61
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010062// AST node visitor which can tell whether a given statement will be breakable
63// when the code is compiled by the full compiler in the debugger. This means
64// that there will be an IC (load/store/call) in the code generated for the
65// debugger to piggybag on.
66class BreakableStatementChecker: public AstVisitor {
67 public:
68 BreakableStatementChecker() : is_breakable_(false) {}
69
70 void Check(Statement* stmt);
71 void Check(Expression* stmt);
72
73 bool is_breakable() { return is_breakable_; }
74
75 private:
76 // AST node visit functions.
77#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
78 AST_NODE_LIST(DECLARE_VISIT)
79#undef DECLARE_VISIT
80
81 bool is_breakable_;
82
83 DISALLOW_COPY_AND_ASSIGN(BreakableStatementChecker);
84};
85
86
Leon Clarked91b9f72010-01-27 17:25:45 +000087// -----------------------------------------------------------------------------
88// Full code generator.
89
90class FullCodeGenerator: public AstVisitor {
91 public:
Andrei Popescu31002712010-02-23 13:46:05 +000092 explicit FullCodeGenerator(MacroAssembler* masm)
Leon Clarked91b9f72010-01-27 17:25:45 +000093 : masm_(masm),
Andrei Popescu31002712010-02-23 13:46:05 +000094 info_(NULL),
Leon Clarked91b9f72010-01-27 17:25:45 +000095 nesting_stack_(NULL),
96 loop_depth_(0),
97 location_(kStack),
98 true_label_(NULL),
99 false_label_(NULL) {
100 }
101
Andrei Popescu31002712010-02-23 13:46:05 +0000102 static Handle<Code> MakeCode(CompilationInfo* info);
Leon Clarked91b9f72010-01-27 17:25:45 +0000103
Iain Merrick75681382010-08-19 15:07:18 +0100104 void Generate(CompilationInfo* info);
Leon Clarked91b9f72010-01-27 17:25:45 +0000105
106 private:
107 class Breakable;
108 class Iteration;
109 class TryCatch;
110 class TryFinally;
111 class Finally;
112 class ForIn;
113
114 class NestedStatement BASE_EMBEDDED {
115 public:
116 explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) {
117 // Link into codegen's nesting stack.
118 previous_ = codegen->nesting_stack_;
119 codegen->nesting_stack_ = this;
120 }
121 virtual ~NestedStatement() {
122 // Unlink from codegen's nesting stack.
123 ASSERT_EQ(this, codegen_->nesting_stack_);
124 codegen_->nesting_stack_ = previous_;
125 }
126
127 virtual Breakable* AsBreakable() { return NULL; }
128 virtual Iteration* AsIteration() { return NULL; }
129 virtual TryCatch* AsTryCatch() { return NULL; }
130 virtual TryFinally* AsTryFinally() { return NULL; }
131 virtual Finally* AsFinally() { return NULL; }
132 virtual ForIn* AsForIn() { return NULL; }
133
134 virtual bool IsContinueTarget(Statement* target) { return false; }
135 virtual bool IsBreakTarget(Statement* target) { return false; }
136
137 // Generate code to leave the nested statement. This includes
138 // cleaning up any stack elements in use and restoring the
139 // stack to the expectations of the surrounding statements.
140 // Takes a number of stack elements currently on top of the
141 // nested statement's stack, and returns a number of stack
142 // elements left on top of the surrounding statement's stack.
143 // The generated code must preserve the result register (which
144 // contains the value in case of a return).
145 virtual int Exit(int stack_depth) {
146 // Default implementation for the case where there is
147 // nothing to clean up.
148 return stack_depth;
149 }
150 NestedStatement* outer() { return previous_; }
151 protected:
152 MacroAssembler* masm() { return codegen_->masm(); }
153 private:
154 FullCodeGenerator* codegen_;
155 NestedStatement* previous_;
156 DISALLOW_COPY_AND_ASSIGN(NestedStatement);
157 };
158
159 class Breakable : public NestedStatement {
160 public:
161 Breakable(FullCodeGenerator* codegen,
162 BreakableStatement* break_target)
163 : NestedStatement(codegen),
164 target_(break_target) {}
165 virtual ~Breakable() {}
166 virtual Breakable* AsBreakable() { return this; }
167 virtual bool IsBreakTarget(Statement* statement) {
168 return target_ == statement;
169 }
170 BreakableStatement* statement() { return target_; }
171 Label* break_target() { return &break_target_label_; }
172 private:
173 BreakableStatement* target_;
174 Label break_target_label_;
175 DISALLOW_COPY_AND_ASSIGN(Breakable);
176 };
177
178 class Iteration : public Breakable {
179 public:
180 Iteration(FullCodeGenerator* codegen,
181 IterationStatement* iteration_statement)
182 : Breakable(codegen, iteration_statement) {}
183 virtual ~Iteration() {}
184 virtual Iteration* AsIteration() { return this; }
185 virtual bool IsContinueTarget(Statement* statement) {
186 return this->statement() == statement;
187 }
188 Label* continue_target() { return &continue_target_label_; }
189 private:
190 Label continue_target_label_;
191 DISALLOW_COPY_AND_ASSIGN(Iteration);
192 };
193
194 // The environment inside the try block of a try/catch statement.
195 class TryCatch : public NestedStatement {
196 public:
197 explicit TryCatch(FullCodeGenerator* codegen, Label* catch_entry)
198 : NestedStatement(codegen), catch_entry_(catch_entry) { }
199 virtual ~TryCatch() {}
200 virtual TryCatch* AsTryCatch() { return this; }
201 Label* catch_entry() { return catch_entry_; }
202 virtual int Exit(int stack_depth);
203 private:
204 Label* catch_entry_;
205 DISALLOW_COPY_AND_ASSIGN(TryCatch);
206 };
207
208 // The environment inside the try block of a try/finally statement.
209 class TryFinally : public NestedStatement {
210 public:
211 explicit TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
212 : NestedStatement(codegen), finally_entry_(finally_entry) { }
213 virtual ~TryFinally() {}
214 virtual TryFinally* AsTryFinally() { return this; }
215 Label* finally_entry() { return finally_entry_; }
216 virtual int Exit(int stack_depth);
217 private:
218 Label* finally_entry_;
219 DISALLOW_COPY_AND_ASSIGN(TryFinally);
220 };
221
222 // A FinallyEnvironment represents being inside a finally block.
223 // Abnormal termination of the finally block needs to clean up
224 // the block's parameters from the stack.
225 class Finally : public NestedStatement {
226 public:
227 explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
228 virtual ~Finally() {}
229 virtual Finally* AsFinally() { return this; }
230 virtual int Exit(int stack_depth) {
231 return stack_depth + kFinallyStackElementCount;
232 }
233 private:
234 // Number of extra stack slots occupied during a finally block.
235 static const int kFinallyStackElementCount = 2;
236 DISALLOW_COPY_AND_ASSIGN(Finally);
237 };
238
239 // A ForInEnvironment represents being inside a for-in loop.
240 // Abnormal termination of the for-in block needs to clean up
241 // the block's temporary storage from the stack.
242 class ForIn : public Iteration {
243 public:
244 ForIn(FullCodeGenerator* codegen,
245 ForInStatement* statement)
246 : Iteration(codegen, statement) { }
247 virtual ~ForIn() {}
248 virtual ForIn* AsForIn() { return this; }
249 virtual int Exit(int stack_depth) {
250 return stack_depth + kForInStackElementCount;
251 }
252 private:
Leon Clarked91b9f72010-01-27 17:25:45 +0000253 static const int kForInStackElementCount = 5;
254 DISALLOW_COPY_AND_ASSIGN(ForIn);
255 };
256
257 enum Location {
258 kAccumulator,
259 kStack
260 };
261
262 int SlotOffset(Slot* slot);
263
264 // Emit code to convert a pure value (in a register, slot, as a literal,
265 // or on top of the stack) into the result expected according to an
266 // expression context.
267 void Apply(Expression::Context context, Register reg);
268
269 // Slot cannot have type Slot::LOOKUP.
270 void Apply(Expression::Context context, Slot* slot);
271
272 void Apply(Expression::Context context, Literal* lit);
273 void ApplyTOS(Expression::Context context);
274
275 // Emit code to discard count elements from the top of stack, then convert
276 // a pure value into the result expected according to an expression
277 // context.
278 void DropAndApply(int count, Expression::Context context, Register reg);
279
Leon Clarkef7060e22010-06-03 12:02:55 +0100280 // Set up branch labels for a test expression.
281 void PrepareTest(Label* materialize_true,
282 Label* materialize_false,
283 Label** if_true,
284 Label** if_false);
285
Leon Clarked91b9f72010-01-27 17:25:45 +0000286 // Emit code to convert pure control flow to a pair of labels into the
287 // result expected according to an expression context.
288 void Apply(Expression::Context context,
289 Label* materialize_true,
290 Label* materialize_false);
291
Leon Clarkef7060e22010-06-03 12:02:55 +0100292 // Emit code to convert constant control flow (true or false) into
293 // the result expected according to an expression context.
294 void Apply(Expression::Context context, bool flag);
295
Leon Clarked91b9f72010-01-27 17:25:45 +0000296 // Helper function to convert a pure value into a test context. The value
297 // is expected on the stack or the accumulator, depending on the platform.
298 // See the platform-specific implementation for details.
299 void DoTest(Expression::Context context);
300
301 void Move(Slot* dst, Register source, Register scratch1, Register scratch2);
302 void Move(Register dst, Slot* source);
303
304 // Return an operand used to read/write to a known (ie, non-LOOKUP) slot.
305 // May emit code to traverse the context chain, destroying the scratch
306 // register.
307 MemOperand EmitSlotSearch(Slot* slot, Register scratch);
308
309 void VisitForEffect(Expression* expr) {
310 Expression::Context saved_context = context_;
311 context_ = Expression::kEffect;
312 Visit(expr);
313 context_ = saved_context;
314 }
315
316 void VisitForValue(Expression* expr, Location where) {
317 Expression::Context saved_context = context_;
318 Location saved_location = location_;
319 context_ = Expression::kValue;
320 location_ = where;
321 Visit(expr);
322 context_ = saved_context;
323 location_ = saved_location;
324 }
325
326 void VisitForControl(Expression* expr, Label* if_true, Label* if_false) {
327 Expression::Context saved_context = context_;
328 Label* saved_true = true_label_;
329 Label* saved_false = false_label_;
330 context_ = Expression::kTest;
331 true_label_ = if_true;
332 false_label_ = if_false;
333 Visit(expr);
334 context_ = saved_context;
335 true_label_ = saved_true;
336 false_label_ = saved_false;
337 }
338
339 void VisitForValueControl(Expression* expr,
340 Location where,
341 Label* if_true,
342 Label* if_false) {
343 Expression::Context saved_context = context_;
344 Location saved_location = location_;
345 Label* saved_true = true_label_;
346 Label* saved_false = false_label_;
347 context_ = Expression::kValueTest;
348 location_ = where;
349 true_label_ = if_true;
350 false_label_ = if_false;
351 Visit(expr);
352 context_ = saved_context;
353 location_ = saved_location;
354 true_label_ = saved_true;
355 false_label_ = saved_false;
356 }
357
358 void VisitForControlValue(Expression* expr,
359 Location where,
360 Label* if_true,
361 Label* if_false) {
362 Expression::Context saved_context = context_;
363 Location saved_location = location_;
364 Label* saved_true = true_label_;
365 Label* saved_false = false_label_;
366 context_ = Expression::kTestValue;
367 location_ = where;
368 true_label_ = if_true;
369 false_label_ = if_false;
370 Visit(expr);
371 context_ = saved_context;
372 location_ = saved_location;
373 true_label_ = saved_true;
374 false_label_ = saved_false;
375 }
376
377 void VisitDeclarations(ZoneList<Declaration*>* declarations);
378 void DeclareGlobals(Handle<FixedArray> pairs);
379
Leon Clarkef7060e22010-06-03 12:02:55 +0100380 // Platform-specific code for a variable, constant, or function
381 // declaration. Functions have an initial value.
382 void EmitDeclaration(Variable* variable,
383 Variable::Mode mode,
384 FunctionLiteral* function);
385
Leon Clarked91b9f72010-01-27 17:25:45 +0000386 // Platform-specific return sequence
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100387 void EmitReturnSequence();
Leon Clarked91b9f72010-01-27 17:25:45 +0000388
389 // Platform-specific code sequences for calls
390 void EmitCallWithStub(Call* expr);
391 void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode mode);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100392 void EmitKeyedCallWithIC(Call* expr, Expression* key, RelocInfo::Mode mode);
Leon Clarked91b9f72010-01-27 17:25:45 +0000393
Leon Clarkef7060e22010-06-03 12:02:55 +0100394
395 // Platform-specific code for inline runtime calls.
396 void EmitInlineRuntimeCall(CallRuntime* expr);
397 void EmitIsSmi(ZoneList<Expression*>* arguments);
398 void EmitIsNonNegativeSmi(ZoneList<Expression*>* arguments);
399 void EmitIsObject(ZoneList<Expression*>* arguments);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100400 void EmitIsSpecObject(ZoneList<Expression*>* arguments);
Leon Clarkef7060e22010-06-03 12:02:55 +0100401 void EmitIsUndetectableObject(ZoneList<Expression*>* arguments);
402 void EmitIsFunction(ZoneList<Expression*>* arguments);
403 void EmitIsArray(ZoneList<Expression*>* arguments);
404 void EmitIsRegExp(ZoneList<Expression*>* arguments);
405 void EmitIsConstructCall(ZoneList<Expression*>* arguments);
Iain Merrick75681382010-08-19 15:07:18 +0100406 void EmitIsStringWrapperSafeForDefaultValueOf(
407 ZoneList<Expression*>* arguments);
Leon Clarkef7060e22010-06-03 12:02:55 +0100408 void EmitObjectEquals(ZoneList<Expression*>* arguments);
409 void EmitArguments(ZoneList<Expression*>* arguments);
410 void EmitArgumentsLength(ZoneList<Expression*>* arguments);
411 void EmitClassOf(ZoneList<Expression*>* arguments);
412 void EmitValueOf(ZoneList<Expression*>* arguments);
413 void EmitSetValueOf(ZoneList<Expression*>* arguments);
414 void EmitNumberToString(ZoneList<Expression*>* arguments);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100415 void EmitStringCharFromCode(ZoneList<Expression*>* arguments);
416 void EmitStringCharCodeAt(ZoneList<Expression*>* arguments);
417 void EmitStringCharAt(ZoneList<Expression*>* arguments);
Leon Clarkef7060e22010-06-03 12:02:55 +0100418 void EmitStringCompare(ZoneList<Expression*>* arguments);
419 void EmitStringAdd(ZoneList<Expression*>* arguments);
420 void EmitLog(ZoneList<Expression*>* arguments);
421 void EmitRandomHeapNumber(ZoneList<Expression*>* arguments);
422 void EmitSubString(ZoneList<Expression*>* arguments);
423 void EmitRegExpExec(ZoneList<Expression*>* arguments);
424 void EmitMathPow(ZoneList<Expression*>* arguments);
425 void EmitMathSin(ZoneList<Expression*>* arguments);
426 void EmitMathCos(ZoneList<Expression*>* arguments);
427 void EmitMathSqrt(ZoneList<Expression*>* arguments);
428 void EmitCallFunction(ZoneList<Expression*>* arguments);
429 void EmitRegExpConstructResult(ZoneList<Expression*>* arguments);
430 void EmitSwapElements(ZoneList<Expression*>* arguments);
431 void EmitGetFromCache(ZoneList<Expression*>* arguments);
Ben Murdochbb769b22010-08-11 14:56:33 +0100432 void EmitIsRegExpEquivalent(ZoneList<Expression*>* arguments);
Leon Clarkef7060e22010-06-03 12:02:55 +0100433
Leon Clarked91b9f72010-01-27 17:25:45 +0000434 // Platform-specific code for loading variables.
435 void EmitVariableLoad(Variable* expr, Expression::Context context);
436
Leon Clarkef7060e22010-06-03 12:02:55 +0100437 // Platform-specific support for allocating a new closure based on
438 // the given function info.
439 void EmitNewClosure(Handle<SharedFunctionInfo> info);
440
Leon Clarked91b9f72010-01-27 17:25:45 +0000441 // Platform-specific support for compiling assignments.
442
443 // Load a value from a named property.
444 // The receiver is left on the stack by the IC.
445 void EmitNamedPropertyLoad(Property* expr);
446
447 // Load a value from a keyed property.
448 // The receiver and the key is left on the stack by the IC.
449 void EmitKeyedPropertyLoad(Property* expr);
450
451 // Apply the compound assignment operator. Expects the left operand on top
452 // of the stack and the right one in the accumulator.
453 void EmitBinaryOp(Token::Value op, Expression::Context context);
454
Leon Clarkef7060e22010-06-03 12:02:55 +0100455 // Assign to the given expression as if via '='. The right-hand-side value
456 // is expected in the accumulator.
457 void EmitAssignment(Expression* expr);
458
Leon Clarked91b9f72010-01-27 17:25:45 +0000459 // Complete a variable assignment. The right-hand-side value is expected
460 // in the accumulator.
Leon Clarkef7060e22010-06-03 12:02:55 +0100461 void EmitVariableAssignment(Variable* var,
462 Token::Value op,
463 Expression::Context context);
Leon Clarked91b9f72010-01-27 17:25:45 +0000464
465 // Complete a named property assignment. The receiver is expected on top
466 // of the stack and the right-hand-side value in the accumulator.
467 void EmitNamedPropertyAssignment(Assignment* expr);
468
469 // Complete a keyed property assignment. The receiver and key are
470 // expected on top of the stack and the right-hand-side value in the
471 // accumulator.
472 void EmitKeyedPropertyAssignment(Assignment* expr);
473
Leon Clarkef7060e22010-06-03 12:02:55 +0100474 // Helper for compare operations. Expects the null-value in a register.
475 void EmitNullCompare(bool strict,
476 Register obj,
477 Register null_const,
478 Label* if_true,
479 Label* if_false,
480 Register scratch);
481
Leon Clarked91b9f72010-01-27 17:25:45 +0000482 void SetFunctionPosition(FunctionLiteral* fun);
483 void SetReturnPosition(FunctionLiteral* fun);
484 void SetStatementPosition(Statement* stmt);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100485 void SetExpressionPosition(Expression* expr, int pos);
Leon Clarked91b9f72010-01-27 17:25:45 +0000486 void SetStatementPosition(int pos);
487 void SetSourcePosition(int pos);
488
489 // Non-local control flow support.
490 void EnterFinallyBlock();
491 void ExitFinallyBlock();
492
493 // Loop nesting counter.
494 int loop_depth() { return loop_depth_; }
495 void increment_loop_depth() { loop_depth_++; }
496 void decrement_loop_depth() {
497 ASSERT(loop_depth_ > 0);
498 loop_depth_--;
499 }
500
501 MacroAssembler* masm() { return masm_; }
Andrei Popescu31002712010-02-23 13:46:05 +0000502
503 Handle<Script> script() { return info_->script(); }
504 bool is_eval() { return info_->is_eval(); }
505 FunctionLiteral* function() { return info_->function(); }
506 Scope* scope() { return info_->scope(); }
507
Leon Clarked91b9f72010-01-27 17:25:45 +0000508 static Register result_register();
509 static Register context_register();
510
511 // Set fields in the stack frame. Offsets are the frame pointer relative
512 // offsets defined in, e.g., StandardFrameConstants.
513 void StoreToFrameField(int frame_offset, Register value);
514
515 // Load a value from the current context. Indices are defined as an enum
516 // in v8::internal::Context.
517 void LoadContextField(Register dst, int context_index);
518
519 // AST node visit functions.
520#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
521 AST_NODE_LIST(DECLARE_VISIT)
522#undef DECLARE_VISIT
523 // Handles the shortcutted logical binary operations in VisitBinaryOperation.
524 void EmitLogicalOperation(BinaryOperation* expr);
525
526 MacroAssembler* masm_;
Andrei Popescu31002712010-02-23 13:46:05 +0000527 CompilationInfo* info_;
Leon Clarke4515c472010-02-03 11:58:03 +0000528
Leon Clarked91b9f72010-01-27 17:25:45 +0000529 Label return_label_;
530 NestedStatement* nesting_stack_;
531 int loop_depth_;
532
533 Expression::Context context_;
534 Location location_;
535 Label* true_label_;
536 Label* false_label_;
537
538 friend class NestedStatement;
539
540 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator);
541};
542
543
544} } // namespace v8::internal
545
546#endif // V8_FULL_CODEGEN_H_