blob: 04086d483d9bb1ba7b2e22d1cbef1de9249366a9 [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 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#include "v8.h"
29
Ben Murdoch8b112d22011-06-08 16:22:53 +010030#include "codegen.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000031#include "compiler.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010032#include "debug.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000033#include "full-codegen.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010034#include "liveedit.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010035#include "macro-assembler.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010036#include "prettyprinter.h"
Steve Block6ded16b2010-05-10 14:33:55 +010037#include "scopes.h"
Ben Murdoch69a99ed2011-11-30 16:03:39 +000038#include "scopeinfo.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000039#include "stub-cache.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000040
41namespace v8 {
42namespace internal {
43
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010044void BreakableStatementChecker::Check(Statement* stmt) {
45 Visit(stmt);
46}
47
48
49void BreakableStatementChecker::Check(Expression* expr) {
50 Visit(expr);
51}
52
53
54void BreakableStatementChecker::VisitDeclaration(Declaration* decl) {
55}
56
57
58void BreakableStatementChecker::VisitBlock(Block* stmt) {
59}
60
61
62void BreakableStatementChecker::VisitExpressionStatement(
63 ExpressionStatement* stmt) {
64 // Check if expression is breakable.
65 Visit(stmt->expression());
66}
67
68
69void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
70}
71
72
73void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
74 // If the condition is breakable the if statement is breakable.
75 Visit(stmt->condition());
76}
77
78
79void BreakableStatementChecker::VisitContinueStatement(
80 ContinueStatement* stmt) {
81}
82
83
84void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
85}
86
87
88void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
89 // Return is breakable if the expression is.
90 Visit(stmt->expression());
91}
92
93
Ben Murdoch69a99ed2011-11-30 16:03:39 +000094void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010095 Visit(stmt->expression());
96}
97
98
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010099void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
100 // Switch statements breakable if the tag expression is.
101 Visit(stmt->tag());
102}
103
104
105void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
106 // Mark do while as breakable to avoid adding a break slot in front of it.
107 is_breakable_ = true;
108}
109
110
111void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
112 // Mark while statements breakable if the condition expression is.
113 Visit(stmt->cond());
114}
115
116
117void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
118 // Mark for statements breakable if the condition expression is.
119 if (stmt->cond() != NULL) {
120 Visit(stmt->cond());
121 }
122}
123
124
125void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
126 // Mark for in statements breakable if the enumerable expression is.
127 Visit(stmt->enumerable());
128}
129
130
131void BreakableStatementChecker::VisitTryCatchStatement(
132 TryCatchStatement* stmt) {
133 // Mark try catch as breakable to avoid adding a break slot in front of it.
134 is_breakable_ = true;
135}
136
137
138void BreakableStatementChecker::VisitTryFinallyStatement(
139 TryFinallyStatement* stmt) {
140 // Mark try finally as breakable to avoid adding a break slot in front of it.
141 is_breakable_ = true;
142}
143
144
145void BreakableStatementChecker::VisitDebuggerStatement(
146 DebuggerStatement* stmt) {
147 // The debugger statement is breakable.
148 is_breakable_ = true;
149}
150
151
152void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
153}
154
155
156void BreakableStatementChecker::VisitSharedFunctionInfoLiteral(
157 SharedFunctionInfoLiteral* expr) {
158}
159
160
161void BreakableStatementChecker::VisitConditional(Conditional* expr) {
162}
163
164
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100165void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
166}
167
168
169void BreakableStatementChecker::VisitLiteral(Literal* expr) {
170}
171
172
173void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
174}
175
176
177void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
178}
179
180
181void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
182}
183
184
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100185void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
186 // If assigning to a property (including a global property) the assignment is
187 // breakable.
Ben Murdoch589d6972011-11-30 16:04:58 +0000188 VariableProxy* proxy = expr->target()->AsVariableProxy();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100189 Property* prop = expr->target()->AsProperty();
Ben Murdoch589d6972011-11-30 16:04:58 +0000190 if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100191 is_breakable_ = true;
192 return;
193 }
194
195 // Otherwise the assignment is breakable if the assigned value is.
196 Visit(expr->value());
197}
198
199
200void BreakableStatementChecker::VisitThrow(Throw* expr) {
201 // Throw is breakable if the expression is.
202 Visit(expr->exception());
203}
204
205
206void BreakableStatementChecker::VisitProperty(Property* expr) {
207 // Property load is breakable.
208 is_breakable_ = true;
209}
210
211
212void BreakableStatementChecker::VisitCall(Call* expr) {
213 // Function calls both through IC and call stub are breakable.
214 is_breakable_ = true;
215}
216
217
218void BreakableStatementChecker::VisitCallNew(CallNew* expr) {
219 // Function calls through new are breakable.
220 is_breakable_ = true;
221}
222
223
224void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
225}
226
227
228void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
229 Visit(expr->expression());
230}
231
232
233void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
234 Visit(expr->expression());
235}
236
237
238void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
239 Visit(expr->left());
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +0100240 if (expr->op() != Token::AND &&
241 expr->op() != Token::OR) {
242 Visit(expr->right());
243 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100244}
245
246
247void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
248 Visit(expr->left());
249 Visit(expr->right());
250}
251
252
253void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
254}
255
256
Leon Clarked91b9f72010-01-27 17:25:45 +0000257#define __ ACCESS_MASM(masm())
258
Ben Murdochf87a2032010-10-22 12:50:53 +0100259bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
Steve Block44f0eee2011-05-26 01:26:41 +0100260 Isolate* isolate = info->isolate();
Andrei Popescu31002712010-02-23 13:46:05 +0000261 Handle<Script> script = info->script();
Leon Clarked91b9f72010-01-27 17:25:45 +0000262 if (!script->IsUndefined() && !script->source()->IsUndefined()) {
263 int len = String::cast(script->source())->length();
Steve Block44f0eee2011-05-26 01:26:41 +0100264 isolate->counters()->total_full_codegen_source_size()->Increment(len);
Leon Clarked91b9f72010-01-27 17:25:45 +0000265 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100266 if (FLAG_trace_codegen) {
267 PrintF("Full Compiler - ");
268 }
Andrei Popescu31002712010-02-23 13:46:05 +0000269 CodeGenerator::MakeCodePrologue(info);
Leon Clarked91b9f72010-01-27 17:25:45 +0000270 const int kInitialBufferSize = 4 * KB;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100271 MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100272#ifdef ENABLE_GDB_JIT_INTERFACE
273 masm.positions_recorder()->StartGDBJITLineInfoRecording();
274#endif
Andrei Popescu402d9372010-02-26 13:31:12 +0000275
Andrei Popescu31002712010-02-23 13:46:05 +0000276 FullCodeGenerator cgen(&masm);
Iain Merrick75681382010-08-19 15:07:18 +0100277 cgen.Generate(info);
Leon Clarked91b9f72010-01-27 17:25:45 +0000278 if (cgen.HasStackOverflow()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100279 ASSERT(!isolate->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +0100280 return false;
Leon Clarked91b9f72010-01-27 17:25:45 +0000281 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100282 unsigned table_offset = cgen.EmitStackCheckTable();
Ben Murdochf87a2032010-10-22 12:50:53 +0100283
Ben Murdoch589d6972011-11-30 16:04:58 +0000284 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
Ben Murdochf87a2032010-10-22 12:50:53 +0100285 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100286 code->set_optimizable(info->IsOptimizable());
287 cgen.PopulateDeoptimizationData(code);
288 code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000289 code->set_handler_table(*cgen.handler_table());
290#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch589d6972011-11-30 16:04:58 +0000291 code->set_has_debug_break_slots(
292 info->isolate()->debugger()->IsDebuggerActive());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000293 code->set_compiled_optimizable(info->IsOptimizable());
294#endif // ENABLE_DEBUGGER_SUPPORT
Ben Murdochb0fe1622011-05-05 13:52:32 +0100295 code->set_allow_osr_at_loop_nesting_level(0);
Steve Block1e0659c2011-05-24 12:43:12 +0100296 code->set_stack_check_table_offset(table_offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100297 CodeGenerator::PrintCode(code, info);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000298 info->SetCode(code); // May be an empty handle.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100299#ifdef ENABLE_GDB_JIT_INTERFACE
Steve Block1e0659c2011-05-24 12:43:12 +0100300 if (FLAG_gdbjit && !code.is_null()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100301 GDBJITLineInfo* lineinfo =
302 masm.positions_recorder()->DetachGDBJITLineInfo();
303
304 GDBJIT(RegisterDetailedLineInfo(*code, lineinfo));
305 }
306#endif
Ben Murdochf87a2032010-10-22 12:50:53 +0100307 return !code.is_null();
Leon Clarked91b9f72010-01-27 17:25:45 +0000308}
309
310
Ben Murdochb0fe1622011-05-05 13:52:32 +0100311unsigned FullCodeGenerator::EmitStackCheckTable() {
312 // The stack check table consists of a length (in number of entries)
313 // field, and then a sequence of entries. Each entry is a pair of AST id
314 // and code-relative pc offset.
315 masm()->Align(kIntSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100316 unsigned offset = masm()->pc_offset();
317 unsigned length = stack_checks_.length();
318 __ dd(length);
319 for (unsigned i = 0; i < length; ++i) {
320 __ dd(stack_checks_[i].id);
321 __ dd(stack_checks_[i].pc_and_state);
322 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100323 return offset;
324}
325
326
327void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
328 // Fill in the deoptimization information.
329 ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
330 if (!info_->HasDeoptimizationSupport()) return;
331 int length = bailout_entries_.length();
332 Handle<DeoptimizationOutputData> data =
Steve Block44f0eee2011-05-26 01:26:41 +0100333 isolate()->factory()->
334 NewDeoptimizationOutputData(length, TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100335 for (int i = 0; i < length; i++) {
336 data->SetAstId(i, Smi::FromInt(bailout_entries_[i].id));
337 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
338 }
339 code->set_deoptimization_data(*data);
340}
341
342
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000343void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100344 PrepareForBailoutForId(node->id(), state);
345}
346
347
348void FullCodeGenerator::RecordJSReturnSite(Call* call) {
349 // We record the offset of the function return so we can rebuild the frame
350 // if the function was inlined, i.e., this is the return address in the
351 // inlined function's frame.
352 //
353 // The state is ignored. We defensively set it to TOS_REG, which is the
354 // real state of the unoptimized code at the return site.
355 PrepareForBailoutForId(call->ReturnId(), TOS_REG);
356#ifdef DEBUG
357 // In debug builds, mark the return so we can verify that this function
358 // was called.
359 ASSERT(!call->return_is_recorded_);
360 call->return_is_recorded_ = true;
361#endif
362}
363
364
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000365void FullCodeGenerator::PrepareForBailoutForId(unsigned id, State state) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100366 // There's no need to prepare this code for bailouts from already optimized
367 // code or code that can't be optimized.
368 if (!FLAG_deopt || !info_->HasDeoptimizationSupport()) return;
369 unsigned pc_and_state =
370 StateField::encode(state) | PcField::encode(masm_->pc_offset());
371 BailoutEntry entry = { id, pc_and_state };
372#ifdef DEBUG
373 // Assert that we don't have multiple bailout entries for the same node.
374 for (int i = 0; i < bailout_entries_.length(); i++) {
375 if (bailout_entries_.at(i).id == entry.id) {
376 AstPrinter printer;
377 PrintF("%s", printer.PrintProgram(info_->function()));
378 UNREACHABLE();
379 }
380 }
381#endif // DEBUG
382 bailout_entries_.Add(entry);
383}
384
385
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000386void FullCodeGenerator::RecordStackCheck(unsigned ast_id) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100387 // The pc offset does not need to be encoded and packed together with a
388 // state.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000389 ASSERT(masm_->pc_offset() > 0);
390 BailoutEntry entry = { ast_id, static_cast<unsigned>(masm_->pc_offset()) };
Ben Murdochb0fe1622011-05-05 13:52:32 +0100391 stack_checks_.Add(entry);
392}
393
394
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100395bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100396 // Inline smi case inside loops, but not division and modulo which
397 // are too complicated and take up too much space.
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100398 if (op == Token::DIV ||op == Token::MOD) return false;
399 if (FLAG_always_inline_smi_code) return true;
400 return loop_depth_ > 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100401}
402
403
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100404void FullCodeGenerator::EffectContext::Plug(Register reg) const {
405}
406
407
408void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100409 __ Move(result_register(), reg);
410}
411
412
413void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100414 __ push(reg);
415}
416
417
418void FullCodeGenerator::TestContext::Plug(Register reg) const {
419 // For simplicity we always test the accumulator register.
420 __ Move(result_register(), reg);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000421 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000422 codegen()->DoTest(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100423}
424
425
426void FullCodeGenerator::EffectContext::PlugTOS() const {
427 __ Drop(1);
428}
429
430
431void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
432 __ pop(result_register());
433}
434
435
436void FullCodeGenerator::StackValueContext::PlugTOS() const {
437}
438
439
440void FullCodeGenerator::TestContext::PlugTOS() const {
441 // For simplicity we always test the accumulator register.
442 __ pop(result_register());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000443 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000444 codegen()->DoTest(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100445}
446
447
448void FullCodeGenerator::EffectContext::PrepareTest(
449 Label* materialize_true,
450 Label* materialize_false,
451 Label** if_true,
452 Label** if_false,
453 Label** fall_through) const {
454 // In an effect context, the true and the false case branch to the
455 // same label.
456 *if_true = *if_false = *fall_through = materialize_true;
457}
458
459
460void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
461 Label* materialize_true,
462 Label* materialize_false,
463 Label** if_true,
464 Label** if_false,
465 Label** fall_through) const {
466 *if_true = *fall_through = materialize_true;
467 *if_false = materialize_false;
468}
469
470
471void FullCodeGenerator::StackValueContext::PrepareTest(
472 Label* materialize_true,
473 Label* materialize_false,
474 Label** if_true,
475 Label** if_false,
476 Label** fall_through) const {
477 *if_true = *fall_through = materialize_true;
478 *if_false = materialize_false;
479}
480
481
482void FullCodeGenerator::TestContext::PrepareTest(
483 Label* materialize_true,
484 Label* materialize_false,
485 Label** if_true,
486 Label** if_false,
487 Label** fall_through) const {
488 *if_true = true_label_;
489 *if_false = false_label_;
490 *fall_through = fall_through_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100491}
492
493
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000494void FullCodeGenerator::DoTest(const TestContext* context) {
495 DoTest(context->condition(),
496 context->true_label(),
497 context->false_label(),
498 context->fall_through());
499}
500
501
Leon Clarked91b9f72010-01-27 17:25:45 +0000502void FullCodeGenerator::VisitDeclarations(
503 ZoneList<Declaration*>* declarations) {
504 int length = declarations->length();
Ben Murdoch589d6972011-11-30 16:04:58 +0000505 int global_count = 0;
Leon Clarked91b9f72010-01-27 17:25:45 +0000506 for (int i = 0; i < length; i++) {
507 Declaration* decl = declarations->at(i);
Ben Murdoch589d6972011-11-30 16:04:58 +0000508 EmitDeclaration(decl->proxy(), decl->mode(), decl->fun(), &global_count);
Leon Clarked91b9f72010-01-27 17:25:45 +0000509 }
510
Ben Murdoch589d6972011-11-30 16:04:58 +0000511 // Batch declare global functions and variables.
512 if (global_count > 0) {
Steve Block44f0eee2011-05-26 01:26:41 +0100513 Handle<FixedArray> array =
Ben Murdoch589d6972011-11-30 16:04:58 +0000514 isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
Leon Clarked91b9f72010-01-27 17:25:45 +0000515 for (int j = 0, i = 0; i < length; i++) {
516 Declaration* decl = declarations->at(i);
517 Variable* var = decl->proxy()->var();
Leon Clarked91b9f72010-01-27 17:25:45 +0000518
Ben Murdoch589d6972011-11-30 16:04:58 +0000519 if (var->IsUnallocated()) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000520 array->set(j++, *(var->name()));
521 if (decl->fun() == NULL) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000522 if (var->binding_needs_init()) {
523 // In case this binding needs initialization use the hole.
Leon Clarked91b9f72010-01-27 17:25:45 +0000524 array->set_the_hole(j++);
525 } else {
526 array->set_undefined(j++);
527 }
528 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100529 Handle<SharedFunctionInfo> function =
Ben Murdochf87a2032010-10-22 12:50:53 +0100530 Compiler::BuildFunctionInfo(decl->fun(), script());
Leon Clarked91b9f72010-01-27 17:25:45 +0000531 // Check for stack-overflow exception.
Ben Murdochf87a2032010-10-22 12:50:53 +0100532 if (function.is_null()) {
533 SetStackOverflow();
534 return;
535 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000536 array->set(j++, *function);
537 }
538 }
539 }
540 // Invoke the platform-dependent code generator to do the actual
Ben Murdoch589d6972011-11-30 16:04:58 +0000541 // declaration the global functions and variables.
Leon Clarked91b9f72010-01-27 17:25:45 +0000542 DeclareGlobals(array);
543 }
544}
545
546
Ben Murdoch589d6972011-11-30 16:04:58 +0000547int FullCodeGenerator::DeclareGlobalsFlags() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000548 ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode()));
549 return DeclareGlobalsEvalFlag::encode(is_eval()) |
550 DeclareGlobalsNativeFlag::encode(is_native()) |
551 DeclareGlobalsLanguageMode::encode(language_mode());
Ben Murdoch589d6972011-11-30 16:04:58 +0000552}
553
554
Leon Clarked91b9f72010-01-27 17:25:45 +0000555void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000556 CodeGenerator::RecordPositions(masm_, fun->start_position());
Leon Clarked91b9f72010-01-27 17:25:45 +0000557}
558
559
560void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000561 CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
Leon Clarked91b9f72010-01-27 17:25:45 +0000562}
563
564
565void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100566#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000567 if (!isolate()->debugger()->IsDebuggerActive()) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000568 CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000569 } else {
570 // Check if the statement will be breakable without adding a debug break
571 // slot.
572 BreakableStatementChecker checker;
573 checker.Check(stmt);
574 // Record the statement position right here if the statement is not
575 // breakable. For breakable statements the actual recording of the
576 // position will be postponed to the breakable code (typically an IC).
577 bool position_recorded = CodeGenerator::RecordPositions(
578 masm_, stmt->statement_pos(), !checker.is_breakable());
579 // If the position recording did record a new position generate a debug
580 // break slot to make the statement breakable.
581 if (position_recorded) {
582 Debug::GenerateSlot(masm_);
583 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100584 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000585#else
586 CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
587#endif
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100588}
589
590
591void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100592#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000593 if (!isolate()->debugger()->IsDebuggerActive()) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100594 CodeGenerator::RecordPositions(masm_, pos);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000595 } else {
596 // Check if the expression will be breakable without adding a debug break
597 // slot.
598 BreakableStatementChecker checker;
599 checker.Check(expr);
600 // Record a statement position right here if the expression is not
601 // breakable. For breakable expressions the actual recording of the
602 // position will be postponed to the breakable code (typically an IC).
603 // NOTE this will record a statement position for something which might
604 // not be a statement. As stepping in the debugger will only stop at
605 // statement positions this is used for e.g. the condition expression of
606 // a do while loop.
607 bool position_recorded = CodeGenerator::RecordPositions(
608 masm_, pos, !checker.is_breakable());
609 // If the position recording did record a new position generate a debug
610 // break slot to make the statement breakable.
611 if (position_recorded) {
612 Debug::GenerateSlot(masm_);
613 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000614 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000615#else
616 CodeGenerator::RecordPositions(masm_, pos);
617#endif
Leon Clarked91b9f72010-01-27 17:25:45 +0000618}
619
620
621void FullCodeGenerator::SetStatementPosition(int pos) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000622 CodeGenerator::RecordPositions(masm_, pos);
Leon Clarked91b9f72010-01-27 17:25:45 +0000623}
624
625
Ben Murdochb0fe1622011-05-05 13:52:32 +0100626void FullCodeGenerator::SetSourcePosition(int pos) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000627 if (pos != RelocInfo::kNoPosition) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100628 masm_->positions_recorder()->RecordPosition(pos);
Leon Clarked91b9f72010-01-27 17:25:45 +0000629 }
630}
631
632
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100633// Lookup table for code generators for special runtime calls which are
634// generated inline.
635#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
636 &FullCodeGenerator::Emit##Name,
Steve Block791712a2010-08-27 10:21:07 +0100637
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100638const FullCodeGenerator::InlineFunctionGenerator
639 FullCodeGenerator::kInlineFunctionGenerators[] = {
640 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
641 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
642 };
643#undef INLINE_FUNCTION_GENERATOR_ADDRESS
644
645
646FullCodeGenerator::InlineFunctionGenerator
647 FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100648 int lookup_index =
649 static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
650 ASSERT(lookup_index >= 0);
651 ASSERT(static_cast<size_t>(lookup_index) <
652 ARRAY_SIZE(kInlineFunctionGenerators));
653 return kInlineFunctionGenerators[lookup_index];
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100654}
655
656
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000657void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
658 const Runtime::Function* function = expr->function();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100659 ASSERT(function != NULL);
660 ASSERT(function->intrinsic_type == Runtime::INLINE);
661 InlineFunctionGenerator generator =
662 FindInlineFunctionGenerator(function->function_id);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000663 ((*this).*(generator))(expr);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100664}
665
666
667void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000668 switch (expr->op()) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100669 case Token::COMMA:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000670 return VisitComma(expr);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100671 case Token::OR:
672 case Token::AND:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000673 return VisitLogicalExpression(expr);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100674 default:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000675 return VisitArithmeticExpression(expr);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100676 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100677}
678
679
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000680void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
681 if (context()->IsEffect()) {
682 VisitForEffect(expr);
683 } else if (context()->IsAccumulatorValue()) {
684 VisitForAccumulatorValue(expr);
685 } else if (context()->IsStackValue()) {
686 VisitForStackValue(expr);
687 } else if (context()->IsTest()) {
688 const TestContext* test = TestContext::cast(context());
689 VisitForControl(expr, test->true_label(), test->false_label(),
690 test->fall_through());
691 }
692}
693
694
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000695void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
696 Comment cmnt(masm_, "[ Comma");
697 VisitForEffect(expr->left());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000698 VisitInDuplicateContext(expr->right());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000699}
Leon Clarked91b9f72010-01-27 17:25:45 +0000700
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000701
702void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
703 bool is_logical_and = expr->op() == Token::AND;
704 Comment cmnt(masm_, is_logical_and ? "[ Logical AND" : "[ Logical OR");
705 Expression* left = expr->left();
706 Expression* right = expr->right();
707 int right_id = expr->RightId();
708 Label done;
709
710 if (context()->IsTest()) {
711 Label eval_right;
712 const TestContext* test = TestContext::cast(context());
713 if (is_logical_and) {
714 VisitForControl(left, &eval_right, test->false_label(), &eval_right);
715 } else {
716 VisitForControl(left, test->true_label(), &eval_right, &eval_right);
717 }
718 PrepareForBailoutForId(right_id, NO_REGISTERS);
719 __ bind(&eval_right);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000720
721 } else if (context()->IsAccumulatorValue()) {
722 VisitForAccumulatorValue(left);
723 // We want the value in the accumulator for the test, and on the stack in
724 // case we need it.
725 __ push(result_register());
726 Label discard, restore;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000727 if (is_logical_and) {
728 DoTest(left, &discard, &restore, &restore);
729 } else {
730 DoTest(left, &restore, &discard, &restore);
731 }
732 __ bind(&restore);
733 __ pop(result_register());
734 __ jmp(&done);
735 __ bind(&discard);
736 __ Drop(1);
737 PrepareForBailoutForId(right_id, NO_REGISTERS);
738
739 } else if (context()->IsStackValue()) {
740 VisitForAccumulatorValue(left);
741 // We want the value in the accumulator for the test, and on the stack in
742 // case we need it.
743 __ push(result_register());
744 Label discard;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000745 if (is_logical_and) {
746 DoTest(left, &discard, &done, &discard);
747 } else {
748 DoTest(left, &done, &discard, &discard);
749 }
750 __ bind(&discard);
751 __ Drop(1);
752 PrepareForBailoutForId(right_id, NO_REGISTERS);
753
754 } else {
755 ASSERT(context()->IsEffect());
756 Label eval_right;
757 if (is_logical_and) {
758 VisitForControl(left, &eval_right, &done, &eval_right);
759 } else {
760 VisitForControl(left, &done, &eval_right, &eval_right);
761 }
762 PrepareForBailoutForId(right_id, NO_REGISTERS);
763 __ bind(&eval_right);
764 }
765
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000766 VisitInDuplicateContext(right);
Leon Clarked91b9f72010-01-27 17:25:45 +0000767 __ bind(&done);
768}
769
770
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000771void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
772 Token::Value op = expr->op();
773 Comment cmnt(masm_, "[ ArithmeticExpression");
774 Expression* left = expr->left();
775 Expression* right = expr->right();
776 OverwriteMode mode =
777 left->ResultOverwriteAllowed()
778 ? OVERWRITE_LEFT
779 : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE);
780
781 VisitForStackValue(left);
782 VisitForAccumulatorValue(right);
783
784 SetSourcePosition(expr->position());
785 if (ShouldInlineSmiCase(op)) {
786 EmitInlineSmiBinaryOp(expr, op, mode, left, right);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100787 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000788 EmitBinaryOp(expr, op, mode);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100789 }
790}
791
792
Leon Clarked91b9f72010-01-27 17:25:45 +0000793void FullCodeGenerator::VisitBlock(Block* stmt) {
794 Comment cmnt(masm_, "[ Block");
Ben Murdoch589d6972011-11-30 16:04:58 +0000795 NestedBlock nested_block(this, stmt);
Leon Clarked91b9f72010-01-27 17:25:45 +0000796 SetStatementPosition(stmt);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100797
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000798 Scope* saved_scope = scope();
Ben Murdoch589d6972011-11-30 16:04:58 +0000799 // Push a block context when entering a block with block scoped variables.
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000800 if (stmt->block_scope() != NULL) {
801 { Comment cmnt(masm_, "[ Extend block context");
802 scope_ = stmt->block_scope();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000803 Handle<ScopeInfo> scope_info = scope_->GetScopeInfo();
804 int heap_slots = scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS;
805 __ Push(scope_info);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000806 PushFunctionArgumentForContextAllocation();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000807 if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) {
808 FastNewBlockContextStub stub(heap_slots);
809 __ CallStub(&stub);
810 } else {
811 __ CallRuntime(Runtime::kPushBlockContext, 2);
812 }
813
814 // Replace the context stored in the frame.
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000815 StoreToFrameField(StandardFrameConstants::kContextOffset,
816 context_register());
817 }
818 { Comment cmnt(masm_, "[ Declarations");
819 VisitDeclarations(scope_->declarations());
820 }
821 }
Steve Block1e0659c2011-05-24 12:43:12 +0100822 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +0000823 VisitStatements(stmt->statements());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000824 scope_ = saved_scope;
Ben Murdoch589d6972011-11-30 16:04:58 +0000825 __ bind(nested_block.break_label());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100826 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
Ben Murdoch589d6972011-11-30 16:04:58 +0000827
828 // Pop block context if necessary.
829 if (stmt->block_scope() != NULL) {
830 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
831 // Update local stack frame context field.
832 StoreToFrameField(StandardFrameConstants::kContextOffset,
833 context_register());
834 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000835}
836
837
838void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
839 Comment cmnt(masm_, "[ ExpressionStatement");
840 SetStatementPosition(stmt);
841 VisitForEffect(stmt->expression());
842}
843
844
845void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
846 Comment cmnt(masm_, "[ EmptyStatement");
847 SetStatementPosition(stmt);
848}
849
850
851void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
852 Comment cmnt(masm_, "[ IfStatement");
853 SetStatementPosition(stmt);
854 Label then_part, else_part, done;
855
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100856 if (stmt->HasElseStatement()) {
857 VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100858 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100859 __ bind(&then_part);
860 Visit(stmt->then_statement());
861 __ jmp(&done);
Leon Clarked91b9f72010-01-27 17:25:45 +0000862
Ben Murdochb0fe1622011-05-05 13:52:32 +0100863 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100864 __ bind(&else_part);
865 Visit(stmt->else_statement());
866 } else {
867 VisitForControl(stmt->condition(), &then_part, &done, &then_part);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100868 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100869 __ bind(&then_part);
870 Visit(stmt->then_statement());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100871
872 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100873 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000874 __ bind(&done);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000875 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +0000876}
877
878
879void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
880 Comment cmnt(masm_, "[ ContinueStatement");
881 SetStatementPosition(stmt);
882 NestedStatement* current = nesting_stack_;
883 int stack_depth = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000884 int context_length = 0;
Ben Murdochdb5a90a2011-01-06 18:27:03 +0000885 // When continuing, we clobber the unpredictable value in the accumulator
886 // with one that's safe for GC. If we hit an exit from the try block of
887 // try...finally on our way out, we will unconditionally preserve the
888 // accumulator on the stack.
889 ClearAccumulator();
Leon Clarked91b9f72010-01-27 17:25:45 +0000890 while (!current->IsContinueTarget(stmt->target())) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000891 current = current->Exit(&stack_depth, &context_length);
Leon Clarked91b9f72010-01-27 17:25:45 +0000892 }
893 __ Drop(stack_depth);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000894 if (context_length > 0) {
895 while (context_length > 0) {
896 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
897 --context_length;
898 }
899 StoreToFrameField(StandardFrameConstants::kContextOffset,
900 context_register());
901 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000902
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000903 __ jmp(current->AsIteration()->continue_label());
Leon Clarked91b9f72010-01-27 17:25:45 +0000904}
905
906
907void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
908 Comment cmnt(masm_, "[ BreakStatement");
909 SetStatementPosition(stmt);
910 NestedStatement* current = nesting_stack_;
911 int stack_depth = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000912 int context_length = 0;
Ben Murdochdb5a90a2011-01-06 18:27:03 +0000913 // When breaking, we clobber the unpredictable value in the accumulator
914 // with one that's safe for GC. If we hit an exit from the try block of
915 // try...finally on our way out, we will unconditionally preserve the
916 // accumulator on the stack.
917 ClearAccumulator();
Leon Clarked91b9f72010-01-27 17:25:45 +0000918 while (!current->IsBreakTarget(stmt->target())) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000919 current = current->Exit(&stack_depth, &context_length);
Leon Clarked91b9f72010-01-27 17:25:45 +0000920 }
921 __ Drop(stack_depth);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000922 if (context_length > 0) {
923 while (context_length > 0) {
924 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
925 --context_length;
926 }
927 StoreToFrameField(StandardFrameConstants::kContextOffset,
928 context_register());
929 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000930
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000931 __ jmp(current->AsBreakable()->break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +0000932}
933
934
935void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
936 Comment cmnt(masm_, "[ ReturnStatement");
937 SetStatementPosition(stmt);
938 Expression* expr = stmt->expression();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100939 VisitForAccumulatorValue(expr);
Leon Clarked91b9f72010-01-27 17:25:45 +0000940
941 // Exit all nested statements.
942 NestedStatement* current = nesting_stack_;
943 int stack_depth = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000944 int context_length = 0;
Leon Clarked91b9f72010-01-27 17:25:45 +0000945 while (current != NULL) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000946 current = current->Exit(&stack_depth, &context_length);
Leon Clarked91b9f72010-01-27 17:25:45 +0000947 }
948 __ Drop(stack_depth);
949
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100950 EmitReturnSequence();
Leon Clarked91b9f72010-01-27 17:25:45 +0000951}
952
953
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000954void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
955 Comment cmnt(masm_, "[ WithStatement");
Leon Clarked91b9f72010-01-27 17:25:45 +0000956 SetStatementPosition(stmt);
957
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100958 VisitForStackValue(stmt->expression());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000959 PushFunctionArgumentForContextAllocation();
960 __ CallRuntime(Runtime::kPushWithContext, 2);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000961 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
962
963 { WithOrCatch body(this);
964 Visit(stmt->statement());
965 }
966
967 // Pop context.
968 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
969 // Update local stack frame context field.
Leon Clarked91b9f72010-01-27 17:25:45 +0000970 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
971}
972
973
Leon Clarked91b9f72010-01-27 17:25:45 +0000974void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
975 Comment cmnt(masm_, "[ DoWhileStatement");
976 SetStatementPosition(stmt);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100977 Label body, stack_check;
Leon Clarked91b9f72010-01-27 17:25:45 +0000978
979 Iteration loop_statement(this, stmt);
980 increment_loop_depth();
981
982 __ bind(&body);
983 Visit(stmt->body());
984
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100985 // Record the position of the do while condition and make sure it is
986 // possible to break on the condition.
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000987 __ bind(loop_statement.continue_label());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100988 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100989 SetExpressionPosition(stmt->cond(), stmt->condition_position());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100990 VisitForControl(stmt->cond(),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100991 &stack_check,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000992 loop_statement.break_label(),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100993 &stack_check);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100994
Ben Murdochb0fe1622011-05-05 13:52:32 +0100995 // Check stack before looping.
996 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
997 __ bind(&stack_check);
998 EmitStackCheck(stmt);
999 __ jmp(&body);
1000
1001 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001002 __ bind(loop_statement.break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001003 decrement_loop_depth();
1004}
1005
1006
1007void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1008 Comment cmnt(masm_, "[ WhileStatement");
Ben Murdochb0fe1622011-05-05 13:52:32 +01001009 Label test, body;
Leon Clarked91b9f72010-01-27 17:25:45 +00001010
1011 Iteration loop_statement(this, stmt);
1012 increment_loop_depth();
1013
1014 // Emit the test at the bottom of the loop.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001015 __ jmp(&test);
Leon Clarked91b9f72010-01-27 17:25:45 +00001016
Ben Murdochb0fe1622011-05-05 13:52:32 +01001017 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +00001018 __ bind(&body);
1019 Visit(stmt->body());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001020
1021 // Emit the statement position here as this is where the while
1022 // statement code starts.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001023 __ bind(loop_statement.continue_label());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001024 SetStatementPosition(stmt);
Leon Clarkef7060e22010-06-03 12:02:55 +01001025
Leon Clarked91b9f72010-01-27 17:25:45 +00001026 // Check stack before looping.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001027 EmitStackCheck(stmt);
Leon Clarked91b9f72010-01-27 17:25:45 +00001028
Ben Murdochb0fe1622011-05-05 13:52:32 +01001029 __ bind(&test);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001030 VisitForControl(stmt->cond(),
1031 &body,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001032 loop_statement.break_label(),
1033 loop_statement.break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001034
Ben Murdochb0fe1622011-05-05 13:52:32 +01001035 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001036 __ bind(loop_statement.break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001037 decrement_loop_depth();
1038}
1039
1040
1041void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1042 Comment cmnt(masm_, "[ ForStatement");
Ben Murdochb0fe1622011-05-05 13:52:32 +01001043 Label test, body;
Leon Clarked91b9f72010-01-27 17:25:45 +00001044
1045 Iteration loop_statement(this, stmt);
1046 if (stmt->init() != NULL) {
1047 Visit(stmt->init());
1048 }
1049
1050 increment_loop_depth();
1051 // Emit the test at the bottom of the loop (even if empty).
1052 __ jmp(&test);
1053
Ben Murdochb0fe1622011-05-05 13:52:32 +01001054 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +00001055 __ bind(&body);
1056 Visit(stmt->body());
1057
Ben Murdochb0fe1622011-05-05 13:52:32 +01001058 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001059 __ bind(loop_statement.continue_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001060 SetStatementPosition(stmt);
1061 if (stmt->next() != NULL) {
1062 Visit(stmt->next());
1063 }
1064
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001065 // Emit the statement position here as this is where the for
1066 // statement code starts.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001067 SetStatementPosition(stmt);
Leon Clarked91b9f72010-01-27 17:25:45 +00001068
1069 // Check stack before looping.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001070 EmitStackCheck(stmt);
Leon Clarked91b9f72010-01-27 17:25:45 +00001071
Ben Murdochb0fe1622011-05-05 13:52:32 +01001072 __ bind(&test);
Leon Clarked91b9f72010-01-27 17:25:45 +00001073 if (stmt->cond() != NULL) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001074 VisitForControl(stmt->cond(),
1075 &body,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001076 loop_statement.break_label(),
1077 loop_statement.break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001078 } else {
1079 __ jmp(&body);
1080 }
1081
Ben Murdochb0fe1622011-05-05 13:52:32 +01001082 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001083 __ bind(loop_statement.break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001084 decrement_loop_depth();
1085}
1086
1087
Leon Clarked91b9f72010-01-27 17:25:45 +00001088void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1089 Comment cmnt(masm_, "[ TryCatchStatement");
1090 SetStatementPosition(stmt);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001091 // The try block adds a handler to the exception handler chain before
1092 // entering, and removes it again when exiting normally. If an exception
1093 // is thrown during execution of the try block, the handler is consumed
1094 // and control is passed to the catch block with the exception in the
1095 // result register.
Leon Clarked91b9f72010-01-27 17:25:45 +00001096
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001097 Label try_entry, handler_entry, exit;
1098 __ jmp(&try_entry);
1099 __ bind(&handler_entry);
1100 handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1101 // Exception handler code, the exception is in the result register.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001102 // Extend the context before executing the catch block.
1103 { Comment cmnt(masm_, "[ Extend catch context");
1104 __ Push(stmt->variable()->name());
1105 __ push(result_register());
1106 PushFunctionArgumentForContextAllocation();
1107 __ CallRuntime(Runtime::kPushCatchContext, 3);
1108 StoreToFrameField(StandardFrameConstants::kContextOffset,
1109 context_register());
Leon Clarked91b9f72010-01-27 17:25:45 +00001110 }
1111
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001112 Scope* saved_scope = scope();
1113 scope_ = stmt->scope();
1114 ASSERT(scope_->declarations()->is_empty());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001115 { WithOrCatch catch_body(this);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001116 Visit(stmt->catch_block());
1117 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001118 // Restore the context.
1119 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1120 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001121 scope_ = saved_scope;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001122 __ jmp(&exit);
Leon Clarked91b9f72010-01-27 17:25:45 +00001123
1124 // Try block code. Sets up the exception handler chain.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001125 __ bind(&try_entry);
1126 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER, stmt->index());
1127 { TryCatch try_body(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001128 Visit(stmt->try_block());
Leon Clarked91b9f72010-01-27 17:25:45 +00001129 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001130 __ PopTryHandler();
1131 __ bind(&exit);
Leon Clarked91b9f72010-01-27 17:25:45 +00001132}
1133
1134
1135void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1136 Comment cmnt(masm_, "[ TryFinallyStatement");
1137 SetStatementPosition(stmt);
1138 // Try finally is compiled by setting up a try-handler on the stack while
1139 // executing the try body, and removing it again afterwards.
1140 //
1141 // The try-finally construct can enter the finally block in three ways:
1142 // 1. By exiting the try-block normally. This removes the try-handler and
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001143 // calls the finally block code before continuing.
Leon Clarked91b9f72010-01-27 17:25:45 +00001144 // 2. By exiting the try-block with a function-local control flow transfer
1145 // (break/continue/return). The site of the, e.g., break removes the
1146 // try handler and calls the finally block code before continuing
1147 // its outward control transfer.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001148 // 3. By exiting the try-block with a thrown exception.
Leon Clarked91b9f72010-01-27 17:25:45 +00001149 // This can happen in nested function calls. It traverses the try-handler
1150 // chain and consumes the try-handler entry before jumping to the
1151 // handler code. The handler code then calls the finally-block before
1152 // rethrowing the exception.
1153 //
1154 // The finally block must assume a return address on top of the stack
1155 // (or in the link register on ARM chips) and a value (return value or
1156 // exception) in the result register (rax/eax/r0), both of which must
1157 // be preserved. The return address isn't GC-safe, so it should be
1158 // cooked before GC.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001159 Label try_entry, handler_entry, finally_entry;
Leon Clarked91b9f72010-01-27 17:25:45 +00001160
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001161 // Jump to try-handler setup and try-block code.
1162 __ jmp(&try_entry);
1163 __ bind(&handler_entry);
1164 handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1165 // Exception handler code. This code is only executed when an exception
1166 // is thrown. The exception is in the result register, and must be
1167 // preserved by the finally block. Call the finally block and then
1168 // rethrow the exception if it returns.
1169 __ Call(&finally_entry);
1170 __ push(result_register());
1171 __ CallRuntime(Runtime::kReThrow, 1);
Leon Clarked91b9f72010-01-27 17:25:45 +00001172
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001173 // Finally block implementation.
Leon Clarked91b9f72010-01-27 17:25:45 +00001174 __ bind(&finally_entry);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001175 EnterFinallyBlock();
1176 { Finally finally_body(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001177 Visit(stmt->finally_block());
Leon Clarked91b9f72010-01-27 17:25:45 +00001178 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001179 ExitFinallyBlock(); // Return to the calling code.
Leon Clarked91b9f72010-01-27 17:25:45 +00001180
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001181 // Setup try handler.
1182 __ bind(&try_entry);
1183 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER, stmt->index());
1184 { TryFinally try_body(this, &finally_entry);
Leon Clarked91b9f72010-01-27 17:25:45 +00001185 Visit(stmt->try_block());
Leon Clarked91b9f72010-01-27 17:25:45 +00001186 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001187 __ PopTryHandler();
Ben Murdochdb5a90a2011-01-06 18:27:03 +00001188 // Execute the finally block on the way out. Clobber the unpredictable
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001189 // value in the result register with one that's safe for GC because the
1190 // finally block will unconditionally preserve the result register on the
1191 // stack.
Ben Murdochdb5a90a2011-01-06 18:27:03 +00001192 ClearAccumulator();
Leon Clarked91b9f72010-01-27 17:25:45 +00001193 __ Call(&finally_entry);
1194}
1195
1196
1197void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1198#ifdef ENABLE_DEBUGGER_SUPPORT
1199 Comment cmnt(masm_, "[ DebuggerStatement");
1200 SetStatementPosition(stmt);
Leon Clarke4515c472010-02-03 11:58:03 +00001201
Andrei Popescu402d9372010-02-26 13:31:12 +00001202 __ DebugBreak();
Leon Clarked91b9f72010-01-27 17:25:45 +00001203 // Ignore the return value.
1204#endif
1205}
1206
1207
Leon Clarked91b9f72010-01-27 17:25:45 +00001208void FullCodeGenerator::VisitConditional(Conditional* expr) {
1209 Comment cmnt(masm_, "[ Conditional");
1210 Label true_case, false_case, done;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001211 VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
Leon Clarked91b9f72010-01-27 17:25:45 +00001212
Ben Murdochb0fe1622011-05-05 13:52:32 +01001213 PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +00001214 __ bind(&true_case);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001215 SetExpressionPosition(expr->then_expression(),
1216 expr->then_expression_position());
Ben Murdochf87a2032010-10-22 12:50:53 +01001217 if (context()->IsTest()) {
1218 const TestContext* for_test = TestContext::cast(context());
1219 VisitForControl(expr->then_expression(),
1220 for_test->true_label(),
1221 for_test->false_label(),
1222 NULL);
1223 } else {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001224 VisitInDuplicateContext(expr->then_expression());
Leon Clarked91b9f72010-01-27 17:25:45 +00001225 __ jmp(&done);
1226 }
1227
Ben Murdochb0fe1622011-05-05 13:52:32 +01001228 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +00001229 __ bind(&false_case);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001230 SetExpressionPosition(expr->else_expression(),
1231 expr->else_expression_position());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001232 VisitInDuplicateContext(expr->else_expression());
Leon Clarked91b9f72010-01-27 17:25:45 +00001233 // If control flow falls through Visit, merge it with true case here.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001234 if (!context()->IsTest()) {
Leon Clarked91b9f72010-01-27 17:25:45 +00001235 __ bind(&done);
1236 }
1237}
1238
1239
Leon Clarked91b9f72010-01-27 17:25:45 +00001240void FullCodeGenerator::VisitLiteral(Literal* expr) {
1241 Comment cmnt(masm_, "[ Literal");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001242 context()->Plug(expr->handle());
Leon Clarked91b9f72010-01-27 17:25:45 +00001243}
1244
1245
Leon Clarkef7060e22010-06-03 12:02:55 +01001246void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1247 Comment cmnt(masm_, "[ FunctionLiteral");
1248
1249 // Build the function boilerplate and instantiate it.
1250 Handle<SharedFunctionInfo> function_info =
Ben Murdochf87a2032010-10-22 12:50:53 +01001251 Compiler::BuildFunctionInfo(expr, script());
1252 if (function_info.is_null()) {
1253 SetStackOverflow();
1254 return;
1255 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001256 EmitNewClosure(function_info, expr->pretenure());
Leon Clarkef7060e22010-06-03 12:02:55 +01001257}
1258
1259
1260void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
1261 SharedFunctionInfoLiteral* expr) {
1262 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001263 EmitNewClosure(expr->shared_function_info(), false);
Leon Clarkef7060e22010-06-03 12:02:55 +01001264}
1265
1266
Leon Clarked91b9f72010-01-27 17:25:45 +00001267void FullCodeGenerator::VisitThrow(Throw* expr) {
1268 Comment cmnt(masm_, "[ Throw");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001269 VisitForStackValue(expr->exception());
Leon Clarked91b9f72010-01-27 17:25:45 +00001270 __ CallRuntime(Runtime::kThrow, 1);
1271 // Never returns here.
1272}
1273
1274
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001275FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
1276 int* stack_depth,
1277 int* context_length) {
Leon Clarked91b9f72010-01-27 17:25:45 +00001278 // The macros used here must preserve the result register.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001279 __ Drop(*stack_depth);
Leon Clarked91b9f72010-01-27 17:25:45 +00001280 __ PopTryHandler();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001281 *stack_depth = 0;
1282 return previous_;
Leon Clarked91b9f72010-01-27 17:25:45 +00001283}
1284
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001285
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001286bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
1287 Expression *sub_expr;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001288 Handle<String> check;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001289 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
1290 EmitLiteralCompareTypeof(expr, sub_expr, check);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001291 return true;
1292 }
1293
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001294 if (expr->IsLiteralCompareUndefined(&sub_expr)) {
1295 EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
1296 return true;
1297 }
1298
1299 if (expr->IsLiteralCompareNull(&sub_expr)) {
1300 EmitLiteralCompareNil(expr, sub_expr, kNullValue);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001301 return true;
1302 }
1303
1304 return false;
1305}
1306
1307
Leon Clarked91b9f72010-01-27 17:25:45 +00001308#undef __
1309
1310
1311} } // namespace v8::internal