blob: 3d562324a092293288a5ef90feba7d6dbe5fdd47 [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);
405 void EmitIsUndetectableObject(ZoneList<Expression*>* arguments);
406 void EmitIsFunction(ZoneList<Expression*>* arguments);
407 void EmitIsArray(ZoneList<Expression*>* arguments);
408 void EmitIsRegExp(ZoneList<Expression*>* arguments);
409 void EmitIsConstructCall(ZoneList<Expression*>* arguments);
410 void EmitObjectEquals(ZoneList<Expression*>* arguments);
411 void EmitArguments(ZoneList<Expression*>* arguments);
412 void EmitArgumentsLength(ZoneList<Expression*>* arguments);
413 void EmitClassOf(ZoneList<Expression*>* arguments);
414 void EmitValueOf(ZoneList<Expression*>* arguments);
415 void EmitSetValueOf(ZoneList<Expression*>* arguments);
416 void EmitNumberToString(ZoneList<Expression*>* arguments);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100417 void EmitStringCharFromCode(ZoneList<Expression*>* arguments);
418 void EmitStringCharCodeAt(ZoneList<Expression*>* arguments);
419 void EmitStringCharAt(ZoneList<Expression*>* arguments);
Leon Clarkef7060e22010-06-03 12:02:55 +0100420 void EmitStringCompare(ZoneList<Expression*>* arguments);
421 void EmitStringAdd(ZoneList<Expression*>* arguments);
422 void EmitLog(ZoneList<Expression*>* arguments);
423 void EmitRandomHeapNumber(ZoneList<Expression*>* arguments);
424 void EmitSubString(ZoneList<Expression*>* arguments);
425 void EmitRegExpExec(ZoneList<Expression*>* arguments);
426 void EmitMathPow(ZoneList<Expression*>* arguments);
427 void EmitMathSin(ZoneList<Expression*>* arguments);
428 void EmitMathCos(ZoneList<Expression*>* arguments);
429 void EmitMathSqrt(ZoneList<Expression*>* arguments);
430 void EmitCallFunction(ZoneList<Expression*>* arguments);
431 void EmitRegExpConstructResult(ZoneList<Expression*>* arguments);
432 void EmitSwapElements(ZoneList<Expression*>* arguments);
433 void EmitGetFromCache(ZoneList<Expression*>* arguments);
434
Leon Clarked91b9f72010-01-27 17:25:45 +0000435 // Platform-specific code for loading variables.
436 void EmitVariableLoad(Variable* expr, Expression::Context context);
437
Leon Clarkef7060e22010-06-03 12:02:55 +0100438 // Platform-specific support for allocating a new closure based on
439 // the given function info.
440 void EmitNewClosure(Handle<SharedFunctionInfo> info);
441
Leon Clarked91b9f72010-01-27 17:25:45 +0000442 // Platform-specific support for compiling assignments.
443
444 // Load a value from a named property.
445 // The receiver is left on the stack by the IC.
446 void EmitNamedPropertyLoad(Property* expr);
447
448 // Load a value from a keyed property.
449 // The receiver and the key is left on the stack by the IC.
450 void EmitKeyedPropertyLoad(Property* expr);
451
452 // Apply the compound assignment operator. Expects the left operand on top
453 // of the stack and the right one in the accumulator.
454 void EmitBinaryOp(Token::Value op, Expression::Context context);
455
Leon Clarkef7060e22010-06-03 12:02:55 +0100456 // Assign to the given expression as if via '='. The right-hand-side value
457 // is expected in the accumulator.
458 void EmitAssignment(Expression* expr);
459
Leon Clarked91b9f72010-01-27 17:25:45 +0000460 // Complete a variable assignment. The right-hand-side value is expected
461 // in the accumulator.
Leon Clarkef7060e22010-06-03 12:02:55 +0100462 void EmitVariableAssignment(Variable* var,
463 Token::Value op,
464 Expression::Context context);
Leon Clarked91b9f72010-01-27 17:25:45 +0000465
466 // Complete a named property assignment. The receiver is expected on top
467 // of the stack and the right-hand-side value in the accumulator.
468 void EmitNamedPropertyAssignment(Assignment* expr);
469
470 // Complete a keyed property assignment. The receiver and key are
471 // expected on top of the stack and the right-hand-side value in the
472 // accumulator.
473 void EmitKeyedPropertyAssignment(Assignment* expr);
474
Leon Clarkef7060e22010-06-03 12:02:55 +0100475 // Helper for compare operations. Expects the null-value in a register.
476 void EmitNullCompare(bool strict,
477 Register obj,
478 Register null_const,
479 Label* if_true,
480 Label* if_false,
481 Register scratch);
482
Leon Clarked91b9f72010-01-27 17:25:45 +0000483 void SetFunctionPosition(FunctionLiteral* fun);
484 void SetReturnPosition(FunctionLiteral* fun);
485 void SetStatementPosition(Statement* stmt);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100486 void SetExpressionPosition(Expression* expr, int pos);
Leon Clarked91b9f72010-01-27 17:25:45 +0000487 void SetStatementPosition(int pos);
488 void SetSourcePosition(int pos);
489
490 // Non-local control flow support.
491 void EnterFinallyBlock();
492 void ExitFinallyBlock();
493
494 // Loop nesting counter.
495 int loop_depth() { return loop_depth_; }
496 void increment_loop_depth() { loop_depth_++; }
497 void decrement_loop_depth() {
498 ASSERT(loop_depth_ > 0);
499 loop_depth_--;
500 }
501
502 MacroAssembler* masm() { return masm_; }
Andrei Popescu31002712010-02-23 13:46:05 +0000503
504 Handle<Script> script() { return info_->script(); }
505 bool is_eval() { return info_->is_eval(); }
506 FunctionLiteral* function() { return info_->function(); }
507 Scope* scope() { return info_->scope(); }
508
Leon Clarked91b9f72010-01-27 17:25:45 +0000509 static Register result_register();
510 static Register context_register();
511
512 // Set fields in the stack frame. Offsets are the frame pointer relative
513 // offsets defined in, e.g., StandardFrameConstants.
514 void StoreToFrameField(int frame_offset, Register value);
515
516 // Load a value from the current context. Indices are defined as an enum
517 // in v8::internal::Context.
518 void LoadContextField(Register dst, int context_index);
519
520 // AST node visit functions.
521#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
522 AST_NODE_LIST(DECLARE_VISIT)
523#undef DECLARE_VISIT
524 // Handles the shortcutted logical binary operations in VisitBinaryOperation.
525 void EmitLogicalOperation(BinaryOperation* expr);
526
527 MacroAssembler* masm_;
Andrei Popescu31002712010-02-23 13:46:05 +0000528 CompilationInfo* info_;
Leon Clarke4515c472010-02-03 11:58:03 +0000529
Leon Clarked91b9f72010-01-27 17:25:45 +0000530 Label return_label_;
531 NestedStatement* nesting_stack_;
532 int loop_depth_;
533
534 Expression::Context context_;
535 Location location_;
536 Label* true_label_;
537 Label* false_label_;
538
539 friend class NestedStatement;
540
541 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator);
542};
543
544
545} } // namespace v8::internal
546
547#endif // V8_FULL_CODEGEN_H_