blob: b056cee92fbdada04b1251248c90ee4d58948cba [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:
Leon Clarke4515c472010-02-03 11:58:03 +000092 enum Mode {
93 PRIMARY,
94 SECONDARY
95 };
96
Andrei Popescu31002712010-02-23 13:46:05 +000097 explicit FullCodeGenerator(MacroAssembler* masm)
Leon Clarked91b9f72010-01-27 17:25:45 +000098 : masm_(masm),
Andrei Popescu31002712010-02-23 13:46:05 +000099 info_(NULL),
Leon Clarked91b9f72010-01-27 17:25:45 +0000100 nesting_stack_(NULL),
101 loop_depth_(0),
102 location_(kStack),
103 true_label_(NULL),
104 false_label_(NULL) {
105 }
106
Andrei Popescu31002712010-02-23 13:46:05 +0000107 static Handle<Code> MakeCode(CompilationInfo* info);
Leon Clarked91b9f72010-01-27 17:25:45 +0000108
Andrei Popescu31002712010-02-23 13:46:05 +0000109 void Generate(CompilationInfo* info, Mode mode);
Leon Clarked91b9f72010-01-27 17:25:45 +0000110
111 private:
112 class Breakable;
113 class Iteration;
114 class TryCatch;
115 class TryFinally;
116 class Finally;
117 class ForIn;
118
119 class NestedStatement BASE_EMBEDDED {
120 public:
121 explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) {
122 // Link into codegen's nesting stack.
123 previous_ = codegen->nesting_stack_;
124 codegen->nesting_stack_ = this;
125 }
126 virtual ~NestedStatement() {
127 // Unlink from codegen's nesting stack.
128 ASSERT_EQ(this, codegen_->nesting_stack_);
129 codegen_->nesting_stack_ = previous_;
130 }
131
132 virtual Breakable* AsBreakable() { return NULL; }
133 virtual Iteration* AsIteration() { return NULL; }
134 virtual TryCatch* AsTryCatch() { return NULL; }
135 virtual TryFinally* AsTryFinally() { return NULL; }
136 virtual Finally* AsFinally() { return NULL; }
137 virtual ForIn* AsForIn() { return NULL; }
138
139 virtual bool IsContinueTarget(Statement* target) { return false; }
140 virtual bool IsBreakTarget(Statement* target) { return false; }
141
142 // Generate code to leave the nested statement. This includes
143 // cleaning up any stack elements in use and restoring the
144 // stack to the expectations of the surrounding statements.
145 // Takes a number of stack elements currently on top of the
146 // nested statement's stack, and returns a number of stack
147 // elements left on top of the surrounding statement's stack.
148 // The generated code must preserve the result register (which
149 // contains the value in case of a return).
150 virtual int Exit(int stack_depth) {
151 // Default implementation for the case where there is
152 // nothing to clean up.
153 return stack_depth;
154 }
155 NestedStatement* outer() { return previous_; }
156 protected:
157 MacroAssembler* masm() { return codegen_->masm(); }
158 private:
159 FullCodeGenerator* codegen_;
160 NestedStatement* previous_;
161 DISALLOW_COPY_AND_ASSIGN(NestedStatement);
162 };
163
164 class Breakable : public NestedStatement {
165 public:
166 Breakable(FullCodeGenerator* codegen,
167 BreakableStatement* break_target)
168 : NestedStatement(codegen),
169 target_(break_target) {}
170 virtual ~Breakable() {}
171 virtual Breakable* AsBreakable() { return this; }
172 virtual bool IsBreakTarget(Statement* statement) {
173 return target_ == statement;
174 }
175 BreakableStatement* statement() { return target_; }
176 Label* break_target() { return &break_target_label_; }
177 private:
178 BreakableStatement* target_;
179 Label break_target_label_;
180 DISALLOW_COPY_AND_ASSIGN(Breakable);
181 };
182
183 class Iteration : public Breakable {
184 public:
185 Iteration(FullCodeGenerator* codegen,
186 IterationStatement* iteration_statement)
187 : Breakable(codegen, iteration_statement) {}
188 virtual ~Iteration() {}
189 virtual Iteration* AsIteration() { return this; }
190 virtual bool IsContinueTarget(Statement* statement) {
191 return this->statement() == statement;
192 }
193 Label* continue_target() { return &continue_target_label_; }
194 private:
195 Label continue_target_label_;
196 DISALLOW_COPY_AND_ASSIGN(Iteration);
197 };
198
199 // The environment inside the try block of a try/catch statement.
200 class TryCatch : public NestedStatement {
201 public:
202 explicit TryCatch(FullCodeGenerator* codegen, Label* catch_entry)
203 : NestedStatement(codegen), catch_entry_(catch_entry) { }
204 virtual ~TryCatch() {}
205 virtual TryCatch* AsTryCatch() { return this; }
206 Label* catch_entry() { return catch_entry_; }
207 virtual int Exit(int stack_depth);
208 private:
209 Label* catch_entry_;
210 DISALLOW_COPY_AND_ASSIGN(TryCatch);
211 };
212
213 // The environment inside the try block of a try/finally statement.
214 class TryFinally : public NestedStatement {
215 public:
216 explicit TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
217 : NestedStatement(codegen), finally_entry_(finally_entry) { }
218 virtual ~TryFinally() {}
219 virtual TryFinally* AsTryFinally() { return this; }
220 Label* finally_entry() { return finally_entry_; }
221 virtual int Exit(int stack_depth);
222 private:
223 Label* finally_entry_;
224 DISALLOW_COPY_AND_ASSIGN(TryFinally);
225 };
226
227 // A FinallyEnvironment represents being inside a finally block.
228 // Abnormal termination of the finally block needs to clean up
229 // the block's parameters from the stack.
230 class Finally : public NestedStatement {
231 public:
232 explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
233 virtual ~Finally() {}
234 virtual Finally* AsFinally() { return this; }
235 virtual int Exit(int stack_depth) {
236 return stack_depth + kFinallyStackElementCount;
237 }
238 private:
239 // Number of extra stack slots occupied during a finally block.
240 static const int kFinallyStackElementCount = 2;
241 DISALLOW_COPY_AND_ASSIGN(Finally);
242 };
243
244 // A ForInEnvironment represents being inside a for-in loop.
245 // Abnormal termination of the for-in block needs to clean up
246 // the block's temporary storage from the stack.
247 class ForIn : public Iteration {
248 public:
249 ForIn(FullCodeGenerator* codegen,
250 ForInStatement* statement)
251 : Iteration(codegen, statement) { }
252 virtual ~ForIn() {}
253 virtual ForIn* AsForIn() { return this; }
254 virtual int Exit(int stack_depth) {
255 return stack_depth + kForInStackElementCount;
256 }
257 private:
Leon Clarked91b9f72010-01-27 17:25:45 +0000258 static const int kForInStackElementCount = 5;
259 DISALLOW_COPY_AND_ASSIGN(ForIn);
260 };
261
262 enum Location {
263 kAccumulator,
264 kStack
265 };
266
267 int SlotOffset(Slot* slot);
268
269 // Emit code to convert a pure value (in a register, slot, as a literal,
270 // or on top of the stack) into the result expected according to an
271 // expression context.
272 void Apply(Expression::Context context, Register reg);
273
274 // Slot cannot have type Slot::LOOKUP.
275 void Apply(Expression::Context context, Slot* slot);
276
277 void Apply(Expression::Context context, Literal* lit);
278 void ApplyTOS(Expression::Context context);
279
280 // Emit code to discard count elements from the top of stack, then convert
281 // a pure value into the result expected according to an expression
282 // context.
283 void DropAndApply(int count, Expression::Context context, Register reg);
284
Leon Clarkef7060e22010-06-03 12:02:55 +0100285 // Set up branch labels for a test expression.
286 void PrepareTest(Label* materialize_true,
287 Label* materialize_false,
288 Label** if_true,
289 Label** if_false);
290
Leon Clarked91b9f72010-01-27 17:25:45 +0000291 // Emit code to convert pure control flow to a pair of labels into the
292 // result expected according to an expression context.
293 void Apply(Expression::Context context,
294 Label* materialize_true,
295 Label* materialize_false);
296
Leon Clarkef7060e22010-06-03 12:02:55 +0100297 // Emit code to convert constant control flow (true or false) into
298 // the result expected according to an expression context.
299 void Apply(Expression::Context context, bool flag);
300
Leon Clarked91b9f72010-01-27 17:25:45 +0000301 // Helper function to convert a pure value into a test context. The value
302 // is expected on the stack or the accumulator, depending on the platform.
303 // See the platform-specific implementation for details.
304 void DoTest(Expression::Context context);
305
306 void Move(Slot* dst, Register source, Register scratch1, Register scratch2);
307 void Move(Register dst, Slot* source);
308
309 // Return an operand used to read/write to a known (ie, non-LOOKUP) slot.
310 // May emit code to traverse the context chain, destroying the scratch
311 // register.
312 MemOperand EmitSlotSearch(Slot* slot, Register scratch);
313
314 void VisitForEffect(Expression* expr) {
315 Expression::Context saved_context = context_;
316 context_ = Expression::kEffect;
317 Visit(expr);
318 context_ = saved_context;
319 }
320
321 void VisitForValue(Expression* expr, Location where) {
322 Expression::Context saved_context = context_;
323 Location saved_location = location_;
324 context_ = Expression::kValue;
325 location_ = where;
326 Visit(expr);
327 context_ = saved_context;
328 location_ = saved_location;
329 }
330
331 void VisitForControl(Expression* expr, Label* if_true, Label* if_false) {
332 Expression::Context saved_context = context_;
333 Label* saved_true = true_label_;
334 Label* saved_false = false_label_;
335 context_ = Expression::kTest;
336 true_label_ = if_true;
337 false_label_ = if_false;
338 Visit(expr);
339 context_ = saved_context;
340 true_label_ = saved_true;
341 false_label_ = saved_false;
342 }
343
344 void VisitForValueControl(Expression* expr,
345 Location where,
346 Label* if_true,
347 Label* if_false) {
348 Expression::Context saved_context = context_;
349 Location saved_location = location_;
350 Label* saved_true = true_label_;
351 Label* saved_false = false_label_;
352 context_ = Expression::kValueTest;
353 location_ = where;
354 true_label_ = if_true;
355 false_label_ = if_false;
356 Visit(expr);
357 context_ = saved_context;
358 location_ = saved_location;
359 true_label_ = saved_true;
360 false_label_ = saved_false;
361 }
362
363 void VisitForControlValue(Expression* expr,
364 Location where,
365 Label* if_true,
366 Label* if_false) {
367 Expression::Context saved_context = context_;
368 Location saved_location = location_;
369 Label* saved_true = true_label_;
370 Label* saved_false = false_label_;
371 context_ = Expression::kTestValue;
372 location_ = where;
373 true_label_ = if_true;
374 false_label_ = if_false;
375 Visit(expr);
376 context_ = saved_context;
377 location_ = saved_location;
378 true_label_ = saved_true;
379 false_label_ = saved_false;
380 }
381
382 void VisitDeclarations(ZoneList<Declaration*>* declarations);
383 void DeclareGlobals(Handle<FixedArray> pairs);
384
Leon Clarkef7060e22010-06-03 12:02:55 +0100385 // Platform-specific code for a variable, constant, or function
386 // declaration. Functions have an initial value.
387 void EmitDeclaration(Variable* variable,
388 Variable::Mode mode,
389 FunctionLiteral* function);
390
Leon Clarked91b9f72010-01-27 17:25:45 +0000391 // Platform-specific return sequence
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100392 void EmitReturnSequence();
Leon Clarked91b9f72010-01-27 17:25:45 +0000393
394 // Platform-specific code sequences for calls
395 void EmitCallWithStub(Call* expr);
396 void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode mode);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100397 void EmitKeyedCallWithIC(Call* expr, Expression* key, RelocInfo::Mode mode);
Leon Clarked91b9f72010-01-27 17:25:45 +0000398
Leon Clarkef7060e22010-06-03 12:02:55 +0100399
400 // Platform-specific code for inline runtime calls.
401 void EmitInlineRuntimeCall(CallRuntime* expr);
402 void EmitIsSmi(ZoneList<Expression*>* arguments);
403 void EmitIsNonNegativeSmi(ZoneList<Expression*>* arguments);
404 void EmitIsObject(ZoneList<Expression*>* arguments);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100405 void EmitIsSpecObject(ZoneList<Expression*>* arguments);
Leon Clarkef7060e22010-06-03 12:02:55 +0100406 void EmitIsUndetectableObject(ZoneList<Expression*>* arguments);
407 void EmitIsFunction(ZoneList<Expression*>* arguments);
408 void EmitIsArray(ZoneList<Expression*>* arguments);
409 void EmitIsRegExp(ZoneList<Expression*>* arguments);
410 void EmitIsConstructCall(ZoneList<Expression*>* arguments);
411 void EmitObjectEquals(ZoneList<Expression*>* arguments);
412 void EmitArguments(ZoneList<Expression*>* arguments);
413 void EmitArgumentsLength(ZoneList<Expression*>* arguments);
414 void EmitClassOf(ZoneList<Expression*>* arguments);
415 void EmitValueOf(ZoneList<Expression*>* arguments);
416 void EmitSetValueOf(ZoneList<Expression*>* arguments);
417 void EmitNumberToString(ZoneList<Expression*>* arguments);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100418 void EmitStringCharFromCode(ZoneList<Expression*>* arguments);
419 void EmitStringCharCodeAt(ZoneList<Expression*>* arguments);
420 void EmitStringCharAt(ZoneList<Expression*>* arguments);
Leon Clarkef7060e22010-06-03 12:02:55 +0100421 void EmitStringCompare(ZoneList<Expression*>* arguments);
422 void EmitStringAdd(ZoneList<Expression*>* arguments);
423 void EmitLog(ZoneList<Expression*>* arguments);
424 void EmitRandomHeapNumber(ZoneList<Expression*>* arguments);
425 void EmitSubString(ZoneList<Expression*>* arguments);
426 void EmitRegExpExec(ZoneList<Expression*>* arguments);
427 void EmitMathPow(ZoneList<Expression*>* arguments);
428 void EmitMathSin(ZoneList<Expression*>* arguments);
429 void EmitMathCos(ZoneList<Expression*>* arguments);
430 void EmitMathSqrt(ZoneList<Expression*>* arguments);
431 void EmitCallFunction(ZoneList<Expression*>* arguments);
432 void EmitRegExpConstructResult(ZoneList<Expression*>* arguments);
433 void EmitSwapElements(ZoneList<Expression*>* arguments);
434 void EmitGetFromCache(ZoneList<Expression*>* arguments);
435
Leon Clarked91b9f72010-01-27 17:25:45 +0000436 // Platform-specific code for loading variables.
437 void EmitVariableLoad(Variable* expr, Expression::Context context);
438
Leon Clarkef7060e22010-06-03 12:02:55 +0100439 // Platform-specific support for allocating a new closure based on
440 // the given function info.
441 void EmitNewClosure(Handle<SharedFunctionInfo> info);
442
Leon Clarked91b9f72010-01-27 17:25:45 +0000443 // Platform-specific support for compiling assignments.
444
445 // Load a value from a named property.
446 // The receiver is left on the stack by the IC.
447 void EmitNamedPropertyLoad(Property* expr);
448
449 // Load a value from a keyed property.
450 // The receiver and the key is left on the stack by the IC.
451 void EmitKeyedPropertyLoad(Property* expr);
452
453 // Apply the compound assignment operator. Expects the left operand on top
454 // of the stack and the right one in the accumulator.
455 void EmitBinaryOp(Token::Value op, Expression::Context context);
456
Leon Clarkef7060e22010-06-03 12:02:55 +0100457 // Assign to the given expression as if via '='. The right-hand-side value
458 // is expected in the accumulator.
459 void EmitAssignment(Expression* expr);
460
Leon Clarked91b9f72010-01-27 17:25:45 +0000461 // Complete a variable assignment. The right-hand-side value is expected
462 // in the accumulator.
Leon Clarkef7060e22010-06-03 12:02:55 +0100463 void EmitVariableAssignment(Variable* var,
464 Token::Value op,
465 Expression::Context context);
Leon Clarked91b9f72010-01-27 17:25:45 +0000466
467 // Complete a named property assignment. The receiver is expected on top
468 // of the stack and the right-hand-side value in the accumulator.
469 void EmitNamedPropertyAssignment(Assignment* expr);
470
471 // Complete a keyed property assignment. The receiver and key are
472 // expected on top of the stack and the right-hand-side value in the
473 // accumulator.
474 void EmitKeyedPropertyAssignment(Assignment* expr);
475
Leon Clarkef7060e22010-06-03 12:02:55 +0100476 // Helper for compare operations. Expects the null-value in a register.
477 void EmitNullCompare(bool strict,
478 Register obj,
479 Register null_const,
480 Label* if_true,
481 Label* if_false,
482 Register scratch);
483
Leon Clarked91b9f72010-01-27 17:25:45 +0000484 void SetFunctionPosition(FunctionLiteral* fun);
485 void SetReturnPosition(FunctionLiteral* fun);
486 void SetStatementPosition(Statement* stmt);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100487 void SetExpressionPosition(Expression* expr, int pos);
Leon Clarked91b9f72010-01-27 17:25:45 +0000488 void SetStatementPosition(int pos);
489 void SetSourcePosition(int pos);
490
491 // Non-local control flow support.
492 void EnterFinallyBlock();
493 void ExitFinallyBlock();
494
495 // Loop nesting counter.
496 int loop_depth() { return loop_depth_; }
497 void increment_loop_depth() { loop_depth_++; }
498 void decrement_loop_depth() {
499 ASSERT(loop_depth_ > 0);
500 loop_depth_--;
501 }
502
503 MacroAssembler* masm() { return masm_; }
Andrei Popescu31002712010-02-23 13:46:05 +0000504
505 Handle<Script> script() { return info_->script(); }
506 bool is_eval() { return info_->is_eval(); }
507 FunctionLiteral* function() { return info_->function(); }
508 Scope* scope() { return info_->scope(); }
509
Leon Clarked91b9f72010-01-27 17:25:45 +0000510 static Register result_register();
511 static Register context_register();
512
513 // Set fields in the stack frame. Offsets are the frame pointer relative
514 // offsets defined in, e.g., StandardFrameConstants.
515 void StoreToFrameField(int frame_offset, Register value);
516
517 // Load a value from the current context. Indices are defined as an enum
518 // in v8::internal::Context.
519 void LoadContextField(Register dst, int context_index);
520
521 // AST node visit functions.
522#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
523 AST_NODE_LIST(DECLARE_VISIT)
524#undef DECLARE_VISIT
525 // Handles the shortcutted logical binary operations in VisitBinaryOperation.
526 void EmitLogicalOperation(BinaryOperation* expr);
527
528 MacroAssembler* masm_;
Andrei Popescu31002712010-02-23 13:46:05 +0000529 CompilationInfo* info_;
Leon Clarke4515c472010-02-03 11:58:03 +0000530
Leon Clarked91b9f72010-01-27 17:25:45 +0000531 Label return_label_;
532 NestedStatement* nesting_stack_;
533 int loop_depth_;
534
535 Expression::Context context_;
536 Location location_;
537 Label* true_label_;
538 Label* false_label_;
539
540 friend class NestedStatement;
541
542 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator);
543};
544
545
546} } // namespace v8::internal
547
548#endif // V8_FULL_CODEGEN_H_