blob: fa835cb0f4575f7290d97cbcb718869e61d53f12 [file] [log] [blame]
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001// Copyright 2009 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "codegen-inl.h"
31#include "compiler.h"
32#include "full-codegen.h"
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000033#include "macro-assembler.h"
sgjesse@chromium.org833cdd72010-02-26 10:06:16 +000034#include "scopes.h"
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000035#include "stub-cache.h"
36#include "debug.h"
ager@chromium.org5c838252010-02-19 08:53:10 +000037#include "liveedit.h"
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000038
39namespace v8 {
40namespace internal {
41
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000042void BreakableStatementChecker::Check(Statement* stmt) {
43 Visit(stmt);
44}
45
46
47void BreakableStatementChecker::Check(Expression* expr) {
48 Visit(expr);
49}
50
51
52void BreakableStatementChecker::VisitDeclaration(Declaration* decl) {
53}
54
55
56void BreakableStatementChecker::VisitBlock(Block* stmt) {
57}
58
59
60void BreakableStatementChecker::VisitExpressionStatement(
61 ExpressionStatement* stmt) {
62 // Check if expression is breakable.
63 Visit(stmt->expression());
64}
65
66
67void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
68}
69
70
71void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
72 // If the condition is breakable the if statement is breakable.
73 Visit(stmt->condition());
74}
75
76
77void BreakableStatementChecker::VisitContinueStatement(
78 ContinueStatement* stmt) {
79}
80
81
82void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
83}
84
85
86void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
87 // Return is breakable if the expression is.
88 Visit(stmt->expression());
89}
90
91
92void BreakableStatementChecker::VisitWithEnterStatement(
93 WithEnterStatement* stmt) {
94 Visit(stmt->expression());
95}
96
97
98void BreakableStatementChecker::VisitWithExitStatement(
99 WithExitStatement* stmt) {
100}
101
102
103void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
104 // Switch statements breakable if the tag expression is.
105 Visit(stmt->tag());
106}
107
108
109void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
110 // Mark do while as breakable to avoid adding a break slot in front of it.
111 is_breakable_ = true;
112}
113
114
115void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
116 // Mark while statements breakable if the condition expression is.
117 Visit(stmt->cond());
118}
119
120
121void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
122 // Mark for statements breakable if the condition expression is.
123 if (stmt->cond() != NULL) {
124 Visit(stmt->cond());
125 }
126}
127
128
129void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
130 // Mark for in statements breakable if the enumerable expression is.
131 Visit(stmt->enumerable());
132}
133
134
135void BreakableStatementChecker::VisitTryCatchStatement(
136 TryCatchStatement* stmt) {
137 // Mark try catch as breakable to avoid adding a break slot in front of it.
138 is_breakable_ = true;
139}
140
141
142void BreakableStatementChecker::VisitTryFinallyStatement(
143 TryFinallyStatement* stmt) {
144 // Mark try finally as breakable to avoid adding a break slot in front of it.
145 is_breakable_ = true;
146}
147
148
149void BreakableStatementChecker::VisitDebuggerStatement(
150 DebuggerStatement* stmt) {
151 // The debugger statement is breakable.
152 is_breakable_ = true;
153}
154
155
156void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
157}
158
159
160void BreakableStatementChecker::VisitSharedFunctionInfoLiteral(
161 SharedFunctionInfoLiteral* expr) {
162}
163
164
165void BreakableStatementChecker::VisitConditional(Conditional* expr) {
166}
167
168
169void BreakableStatementChecker::VisitSlot(Slot* expr) {
170}
171
172
173void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
174}
175
176
177void BreakableStatementChecker::VisitLiteral(Literal* expr) {
178}
179
180
181void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
182}
183
184
185void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
186}
187
188
189void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
190}
191
192
193void BreakableStatementChecker::VisitCatchExtensionObject(
194 CatchExtensionObject* expr) {
195}
196
197
198void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
199 // If assigning to a property (including a global property) the assignment is
200 // breakable.
201 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
202 Property* prop = expr->target()->AsProperty();
203 if (prop != NULL || (var != NULL && var->is_global())) {
204 is_breakable_ = true;
205 return;
206 }
207
208 // Otherwise the assignment is breakable if the assigned value is.
209 Visit(expr->value());
210}
211
212
213void BreakableStatementChecker::VisitThrow(Throw* expr) {
214 // Throw is breakable if the expression is.
215 Visit(expr->exception());
216}
217
218
ricow@chromium.org65fae842010-08-25 15:26:24 +0000219void BreakableStatementChecker::VisitIncrementOperation(
220 IncrementOperation* expr) {
221 UNREACHABLE();
222}
223
224
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000225void BreakableStatementChecker::VisitProperty(Property* expr) {
226 // Property load is breakable.
227 is_breakable_ = true;
228}
229
230
231void BreakableStatementChecker::VisitCall(Call* expr) {
232 // Function calls both through IC and call stub are breakable.
233 is_breakable_ = true;
234}
235
236
237void BreakableStatementChecker::VisitCallNew(CallNew* expr) {
238 // Function calls through new are breakable.
239 is_breakable_ = true;
240}
241
242
243void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
244}
245
246
247void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
248 Visit(expr->expression());
249}
250
251
252void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
253 Visit(expr->expression());
254}
255
256
257void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
258 Visit(expr->left());
259 Visit(expr->right());
260}
261
262
ricow@chromium.org65fae842010-08-25 15:26:24 +0000263void BreakableStatementChecker::VisitCompareToNull(CompareToNull* expr) {
264 Visit(expr->expression());
265}
266
267
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000268void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
269 Visit(expr->left());
270 Visit(expr->right());
271}
272
273
274void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
275}
276
277
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000278#define __ ACCESS_MASM(masm())
279
ager@chromium.org5c838252010-02-19 08:53:10 +0000280Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
281 Handle<Script> script = info->script();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000282 if (!script->IsUndefined() && !script->source()->IsUndefined()) {
283 int len = String::cast(script->source())->length();
284 Counters::total_full_codegen_source_size.Increment(len);
285 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000286 CodeGenerator::MakeCodePrologue(info);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000287 const int kInitialBufferSize = 4 * KB;
288 MacroAssembler masm(NULL, kInitialBufferSize);
ager@chromium.org5c838252010-02-19 08:53:10 +0000289
290 FullCodeGenerator cgen(&masm);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000291 cgen.Generate(info);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000292 if (cgen.HasStackOverflow()) {
293 ASSERT(!Top::has_pending_exception());
294 return Handle<Code>::null();
295 }
296 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000297 return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000298}
299
300
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000301MemOperand FullCodeGenerator::ContextOperand(Register context, int index) {
302 return CodeGenerator::ContextOperand(context, index);
303}
304
305
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000306int FullCodeGenerator::SlotOffset(Slot* slot) {
307 ASSERT(slot != NULL);
308 // Offset is negative because higher indexes are at lower addresses.
309 int offset = -slot->index() * kPointerSize;
310 // Adjust by a (parameter or local) base offset.
311 switch (slot->type()) {
312 case Slot::PARAMETER:
ager@chromium.org5c838252010-02-19 08:53:10 +0000313 offset += (scope()->num_parameters() + 1) * kPointerSize;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000314 break;
315 case Slot::LOCAL:
316 offset += JavaScriptFrameConstants::kLocal0Offset;
317 break;
318 case Slot::CONTEXT:
319 case Slot::LOOKUP:
320 UNREACHABLE();
321 }
322 return offset;
323}
324
325
ricow@chromium.org65fae842010-08-25 15:26:24 +0000326bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
ricow@chromium.org65fae842010-08-25 15:26:24 +0000327 // Inline smi case inside loops, but not division and modulo which
328 // are too complicated and take up too much space.
erik.corry@gmail.comd88afa22010-09-15 12:33:05 +0000329 if (op == Token::DIV ||op == Token::MOD) return false;
330 if (FLAG_always_inline_smi_code) return true;
331 return loop_depth_ > 0;
ricow@chromium.org65fae842010-08-25 15:26:24 +0000332}
333
334
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000335void FullCodeGenerator::EffectContext::Plug(Register reg) const {
336}
337
338
339void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
340 // Move value into place.
341 __ Move(result_register(), reg);
342}
343
344
345void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
346 // Move value into place.
347 __ push(reg);
348}
349
350
351void FullCodeGenerator::TestContext::Plug(Register reg) const {
352 // For simplicity we always test the accumulator register.
353 __ Move(result_register(), reg);
354 codegen()->DoTest(true_label_, false_label_, fall_through_);
355}
356
357
358void FullCodeGenerator::EffectContext::PlugTOS() const {
359 __ Drop(1);
360}
361
362
363void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
364 __ pop(result_register());
365}
366
367
368void FullCodeGenerator::StackValueContext::PlugTOS() const {
369}
370
371
372void FullCodeGenerator::TestContext::PlugTOS() const {
373 // For simplicity we always test the accumulator register.
374 __ pop(result_register());
375 codegen()->DoTest(true_label_, false_label_, fall_through_);
376}
377
378
379void FullCodeGenerator::EffectContext::PrepareTest(
380 Label* materialize_true,
381 Label* materialize_false,
382 Label** if_true,
383 Label** if_false,
384 Label** fall_through) const {
385 // In an effect context, the true and the false case branch to the
386 // same label.
387 *if_true = *if_false = *fall_through = materialize_true;
388}
389
390
391void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
392 Label* materialize_true,
393 Label* materialize_false,
394 Label** if_true,
395 Label** if_false,
396 Label** fall_through) const {
397 *if_true = *fall_through = materialize_true;
398 *if_false = materialize_false;
399}
400
401
402void FullCodeGenerator::StackValueContext::PrepareTest(
403 Label* materialize_true,
404 Label* materialize_false,
405 Label** if_true,
406 Label** if_false,
407 Label** fall_through) const {
408 *if_true = *fall_through = materialize_true;
409 *if_false = materialize_false;
410}
411
412
413void FullCodeGenerator::TestContext::PrepareTest(
414 Label* materialize_true,
415 Label* materialize_false,
416 Label** if_true,
417 Label** if_false,
418 Label** fall_through) const {
419 *if_true = true_label_;
420 *if_false = false_label_;
421 *fall_through = fall_through_;
ricow@chromium.org65fae842010-08-25 15:26:24 +0000422}
423
424
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000425void FullCodeGenerator::VisitDeclarations(
426 ZoneList<Declaration*>* declarations) {
427 int length = declarations->length();
428 int globals = 0;
429 for (int i = 0; i < length; i++) {
430 Declaration* decl = declarations->at(i);
431 Variable* var = decl->proxy()->var();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000432 Slot* slot = var->AsSlot();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000433
434 // If it was not possible to allocate the variable at compile
435 // time, we need to "declare" it at runtime to make sure it
436 // actually exists in the local context.
437 if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
438 VisitDeclaration(decl);
439 } else {
440 // Count global variables and functions for later processing
441 globals++;
442 }
443 }
444
445 // Compute array of global variable and function declarations.
446 // Do nothing in case of no declared global functions or variables.
447 if (globals > 0) {
448 Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED);
449 for (int j = 0, i = 0; i < length; i++) {
450 Declaration* decl = declarations->at(i);
451 Variable* var = decl->proxy()->var();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000452 Slot* slot = var->AsSlot();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000453
454 if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) {
455 array->set(j++, *(var->name()));
456 if (decl->fun() == NULL) {
457 if (var->mode() == Variable::CONST) {
458 // In case this is const property use the hole.
459 array->set_the_hole(j++);
460 } else {
461 array->set_undefined(j++);
462 }
463 } else {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000464 Handle<SharedFunctionInfo> function =
465 Compiler::BuildFunctionInfo(decl->fun(), script(), this);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000466 // Check for stack-overflow exception.
467 if (HasStackOverflow()) return;
468 array->set(j++, *function);
469 }
470 }
471 }
472 // Invoke the platform-dependent code generator to do the actual
473 // declaration the global variables and functions.
474 DeclareGlobals(array);
475 }
476}
477
478
479void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
480 if (FLAG_debug_info) {
481 CodeGenerator::RecordPositions(masm_, fun->start_position());
482 }
483}
484
485
486void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
487 if (FLAG_debug_info) {
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000488 CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000489 }
490}
491
492
493void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
494 if (FLAG_debug_info) {
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000495#ifdef ENABLE_DEBUGGER_SUPPORT
496 if (!Debugger::IsDebuggerActive()) {
497 CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
498 } else {
499 // Check if the statement will be breakable without adding a debug break
500 // slot.
501 BreakableStatementChecker checker;
502 checker.Check(stmt);
503 // Record the statement position right here if the statement is not
504 // breakable. For breakable statements the actual recording of the
505 // position will be postponed to the breakable code (typically an IC).
506 bool position_recorded = CodeGenerator::RecordPositions(
507 masm_, stmt->statement_pos(), !checker.is_breakable());
508 // If the position recording did record a new position generate a debug
509 // break slot to make the statement breakable.
510 if (position_recorded) {
511 Debug::GenerateSlot(masm_);
512 }
513 }
514#else
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000515 CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000516#endif
517 }
518}
519
520
521void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
522 if (FLAG_debug_info) {
523#ifdef ENABLE_DEBUGGER_SUPPORT
524 if (!Debugger::IsDebuggerActive()) {
525 CodeGenerator::RecordPositions(masm_, pos);
526 } else {
527 // Check if the expression will be breakable without adding a debug break
528 // slot.
529 BreakableStatementChecker checker;
530 checker.Check(expr);
531 // Record a statement position right here if the expression is not
532 // breakable. For breakable expressions the actual recording of the
533 // position will be postponed to the breakable code (typically an IC).
534 // NOTE this will record a statement position for something which might
535 // not be a statement. As stepping in the debugger will only stop at
536 // statement positions this is used for e.g. the condition expression of
537 // a do while loop.
538 bool position_recorded = CodeGenerator::RecordPositions(
539 masm_, pos, !checker.is_breakable());
540 // If the position recording did record a new position generate a debug
541 // break slot to make the statement breakable.
542 if (position_recorded) {
543 Debug::GenerateSlot(masm_);
544 }
545 }
546#else
547 CodeGenerator::RecordPositions(masm_, pos);
548#endif
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000549 }
550}
551
552
553void FullCodeGenerator::SetStatementPosition(int pos) {
554 if (FLAG_debug_info) {
555 CodeGenerator::RecordPositions(masm_, pos);
556 }
557}
558
559
560void FullCodeGenerator::SetSourcePosition(int pos) {
561 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) {
562 masm_->RecordPosition(pos);
563 }
564}
565
566
erik.corry@gmail.comd88afa22010-09-15 12:33:05 +0000567// Lookup table for code generators for special runtime calls which are
568// generated inline.
569#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
570 &FullCodeGenerator::Emit##Name,
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000571
erik.corry@gmail.comd88afa22010-09-15 12:33:05 +0000572const FullCodeGenerator::InlineFunctionGenerator
573 FullCodeGenerator::kInlineFunctionGenerators[] = {
574 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
575 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
576 };
577#undef INLINE_FUNCTION_GENERATOR_ADDRESS
578
579
580FullCodeGenerator::InlineFunctionGenerator
581 FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
582 return kInlineFunctionGenerators[
583 static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
584}
585
586
587void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
588 ZoneList<Expression*>* args = node->arguments();
589 Handle<String> name = node->name();
590 Runtime::Function* function = node->function();
591 ASSERT(function != NULL);
592 ASSERT(function->intrinsic_type == Runtime::INLINE);
593 InlineFunctionGenerator generator =
594 FindInlineFunctionGenerator(function->function_id);
595 ASSERT(generator != NULL);
596 ((*this).*(generator))(args);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000597}
598
599
600void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
601 Comment cmnt(masm_, "[ BinaryOperation");
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000602 Token::Value op = expr->op();
603 Expression* left = expr->left();
604 Expression* right = expr->right();
ricow@chromium.org65fae842010-08-25 15:26:24 +0000605
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000606 OverwriteMode mode = NO_OVERWRITE;
607 if (left->ResultOverwriteAllowed()) {
608 mode = OVERWRITE_LEFT;
609 } else if (right->ResultOverwriteAllowed()) {
610 mode = OVERWRITE_RIGHT;
ricow@chromium.org65fae842010-08-25 15:26:24 +0000611 }
612
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000613 switch (op) {
ricow@chromium.org65fae842010-08-25 15:26:24 +0000614 case Token::COMMA:
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000615 VisitForEffect(left);
616 Visit(right);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000617 break;
618
619 case Token::OR:
620 case Token::AND:
621 EmitLogicalOperation(expr);
622 break;
623
624 case Token::ADD:
625 case Token::SUB:
626 case Token::DIV:
627 case Token::MOD:
628 case Token::MUL:
629 case Token::BIT_OR:
630 case Token::BIT_AND:
631 case Token::BIT_XOR:
632 case Token::SHL:
633 case Token::SHR:
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000634 case Token::SAR: {
635 // Figure out if either of the operands is a constant.
636 ConstantOperand constant = ShouldInlineSmiCase(op)
637 ? GetConstantOperand(op, left, right)
638 : kNoConstants;
639
640 // Load only the operands that we need to materialize.
641 if (constant == kNoConstants) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000642 VisitForStackValue(left);
643 VisitForAccumulatorValue(right);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000644 } else if (constant == kRightConstant) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000645 VisitForAccumulatorValue(left);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000646 } else {
647 ASSERT(constant == kLeftConstant);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000648 VisitForAccumulatorValue(right);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000649 }
650
ricow@chromium.org65fae842010-08-25 15:26:24 +0000651 SetSourcePosition(expr->position());
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000652 if (ShouldInlineSmiCase(op)) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000653 EmitInlineSmiBinaryOp(expr, op, mode, left, right, constant);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000654 } else {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000655 EmitBinaryOp(op, mode);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000656 }
ricow@chromium.org65fae842010-08-25 15:26:24 +0000657 break;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000658 }
ricow@chromium.org65fae842010-08-25 15:26:24 +0000659
660 default:
661 UNREACHABLE();
662 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000663}
664
665
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000666void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
667 Label eval_right, done;
668
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000669 context()->EmitLogicalLeft(expr, &eval_right, &done);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000670
671 __ bind(&eval_right);
672 Visit(expr->right());
673
674 __ bind(&done);
675}
676
677
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000678void FullCodeGenerator::EffectContext::EmitLogicalLeft(BinaryOperation* expr,
679 Label* eval_right,
680 Label* done) const {
681 if (expr->op() == Token::OR) {
682 codegen()->VisitForControl(expr->left(), done, eval_right, eval_right);
683 } else {
684 ASSERT(expr->op() == Token::AND);
685 codegen()->VisitForControl(expr->left(), eval_right, done, eval_right);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000686 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000687}
ricow@chromium.org65fae842010-08-25 15:26:24 +0000688
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000689
690void FullCodeGenerator::AccumulatorValueContext::EmitLogicalLeft(
691 BinaryOperation* expr,
692 Label* eval_right,
693 Label* done) const {
694 codegen()->Visit(expr->left());
695 // We want the value in the accumulator for the test, and on the stack in case
696 // we need it.
697 __ push(result_register());
698 Label discard, restore;
699 if (expr->op() == Token::OR) {
700 codegen()->DoTest(&restore, &discard, &restore);
701 } else {
702 ASSERT(expr->op() == Token::AND);
703 codegen()->DoTest(&discard, &restore, &restore);
704 }
705 __ bind(&restore);
706 __ pop(result_register());
707 __ jmp(done);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000708 __ bind(&discard);
709 __ Drop(1);
710}
711
712
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000713void FullCodeGenerator::StackValueContext::EmitLogicalLeft(
714 BinaryOperation* expr,
715 Label* eval_right,
716 Label* done) const {
717 codegen()->VisitForAccumulatorValue(expr->left());
718 // We want the value in the accumulator for the test, and on the stack in case
719 // we need it.
720 __ push(result_register());
721 Label discard;
722 if (expr->op() == Token::OR) {
723 codegen()->DoTest(done, &discard, &discard);
724 } else {
725 ASSERT(expr->op() == Token::AND);
726 codegen()->DoTest(&discard, done, &discard);
727 }
728 __ bind(&discard);
729 __ Drop(1);
730}
731
732
733void FullCodeGenerator::TestContext::EmitLogicalLeft(BinaryOperation* expr,
734 Label* eval_right,
735 Label* done) const {
736 if (expr->op() == Token::OR) {
737 codegen()->VisitForControl(expr->left(),
738 true_label_, eval_right, eval_right);
739 } else {
740 ASSERT(expr->op() == Token::AND);
741 codegen()->VisitForControl(expr->left(),
742 eval_right, false_label_, eval_right);
743 }
744}
745
746
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000747void FullCodeGenerator::VisitBlock(Block* stmt) {
748 Comment cmnt(masm_, "[ Block");
749 Breakable nested_statement(this, stmt);
750 SetStatementPosition(stmt);
751 VisitStatements(stmt->statements());
752 __ bind(nested_statement.break_target());
753}
754
755
756void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
757 Comment cmnt(masm_, "[ ExpressionStatement");
758 SetStatementPosition(stmt);
759 VisitForEffect(stmt->expression());
760}
761
762
763void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
764 Comment cmnt(masm_, "[ EmptyStatement");
765 SetStatementPosition(stmt);
766}
767
768
769void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
770 Comment cmnt(masm_, "[ IfStatement");
771 SetStatementPosition(stmt);
772 Label then_part, else_part, done;
773
ricow@chromium.org65fae842010-08-25 15:26:24 +0000774 if (stmt->HasElseStatement()) {
775 VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
776 __ bind(&then_part);
777 Visit(stmt->then_statement());
778 __ jmp(&done);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000779
ricow@chromium.org65fae842010-08-25 15:26:24 +0000780 __ bind(&else_part);
781 Visit(stmt->else_statement());
782 } else {
783 VisitForControl(stmt->condition(), &then_part, &done, &then_part);
784 __ bind(&then_part);
785 Visit(stmt->then_statement());
786 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000787 __ bind(&done);
788}
789
790
791void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
792 Comment cmnt(masm_, "[ ContinueStatement");
793 SetStatementPosition(stmt);
794 NestedStatement* current = nesting_stack_;
795 int stack_depth = 0;
796 while (!current->IsContinueTarget(stmt->target())) {
797 stack_depth = current->Exit(stack_depth);
798 current = current->outer();
799 }
800 __ Drop(stack_depth);
801
802 Iteration* loop = current->AsIteration();
803 __ jmp(loop->continue_target());
804}
805
806
807void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
808 Comment cmnt(masm_, "[ BreakStatement");
809 SetStatementPosition(stmt);
810 NestedStatement* current = nesting_stack_;
811 int stack_depth = 0;
812 while (!current->IsBreakTarget(stmt->target())) {
813 stack_depth = current->Exit(stack_depth);
814 current = current->outer();
815 }
816 __ Drop(stack_depth);
817
818 Breakable* target = current->AsBreakable();
819 __ jmp(target->break_target());
820}
821
822
823void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
824 Comment cmnt(masm_, "[ ReturnStatement");
825 SetStatementPosition(stmt);
826 Expression* expr = stmt->expression();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000827 VisitForAccumulatorValue(expr);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000828
829 // Exit all nested statements.
830 NestedStatement* current = nesting_stack_;
831 int stack_depth = 0;
832 while (current != NULL) {
833 stack_depth = current->Exit(stack_depth);
834 current = current->outer();
835 }
836 __ Drop(stack_depth);
837
ager@chromium.org2cc82ae2010-06-14 07:35:38 +0000838 EmitReturnSequence();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000839}
840
841
842void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
843 Comment cmnt(masm_, "[ WithEnterStatement");
844 SetStatementPosition(stmt);
845
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000846 VisitForStackValue(stmt->expression());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000847 if (stmt->is_catch_block()) {
848 __ CallRuntime(Runtime::kPushCatchContext, 1);
849 } else {
850 __ CallRuntime(Runtime::kPushContext, 1);
851 }
852 // Both runtime calls return the new context in both the context and the
853 // result registers.
854
855 // Update local stack frame context field.
856 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
857}
858
859
860void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
861 Comment cmnt(masm_, "[ WithExitStatement");
862 SetStatementPosition(stmt);
863
864 // Pop context.
865 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
866 // Update local stack frame context field.
867 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
868}
869
870
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000871void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
872 Comment cmnt(masm_, "[ DoWhileStatement");
873 SetStatementPosition(stmt);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000874 Label body, stack_limit_hit, stack_check_success, done;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000875
876 Iteration loop_statement(this, stmt);
877 increment_loop_depth();
878
879 __ bind(&body);
880 Visit(stmt->body());
881
882 // Check stack before looping.
883 __ StackLimitCheck(&stack_limit_hit);
884 __ bind(&stack_check_success);
885
ricow@chromium.org65fae842010-08-25 15:26:24 +0000886 // Record the position of the do while condition and make sure it is
887 // possible to break on the condition.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000888 __ bind(loop_statement.continue_target());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000889 SetExpressionPosition(stmt->cond(), stmt->condition_position());
ricow@chromium.org65fae842010-08-25 15:26:24 +0000890 VisitForControl(stmt->cond(),
891 &body,
892 loop_statement.break_target(),
893 loop_statement.break_target());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000894
ricow@chromium.org65fae842010-08-25 15:26:24 +0000895 __ bind(loop_statement.break_target());
896 __ jmp(&done);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000897
898 __ bind(&stack_limit_hit);
899 StackCheckStub stack_stub;
900 __ CallStub(&stack_stub);
901 __ jmp(&stack_check_success);
902
ricow@chromium.org65fae842010-08-25 15:26:24 +0000903 __ bind(&done);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000904 decrement_loop_depth();
905}
906
907
908void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
909 Comment cmnt(masm_, "[ WhileStatement");
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000910 Label body, stack_limit_hit, stack_check_success, done;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000911
912 Iteration loop_statement(this, stmt);
913 increment_loop_depth();
914
915 // Emit the test at the bottom of the loop.
916 __ jmp(loop_statement.continue_target());
917
918 __ bind(&body);
919 Visit(stmt->body());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000920 __ bind(loop_statement.continue_target());
ricow@chromium.org65fae842010-08-25 15:26:24 +0000921
922 // Emit the statement position here as this is where the while
923 // statement code starts.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000924 SetStatementPosition(stmt);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000925
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000926 // Check stack before looping.
927 __ StackLimitCheck(&stack_limit_hit);
928 __ bind(&stack_check_success);
929
ricow@chromium.org65fae842010-08-25 15:26:24 +0000930 VisitForControl(stmt->cond(),
931 &body,
932 loop_statement.break_target(),
933 loop_statement.break_target());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000934
935 __ bind(loop_statement.break_target());
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000936 __ jmp(&done);
937
938 __ bind(&stack_limit_hit);
939 StackCheckStub stack_stub;
940 __ CallStub(&stack_stub);
941 __ jmp(&stack_check_success);
942
943 __ bind(&done);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000944 decrement_loop_depth();
945}
946
947
948void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
949 Comment cmnt(masm_, "[ ForStatement");
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000950 Label test, body, stack_limit_hit, stack_check_success;
951
952 Iteration loop_statement(this, stmt);
953 if (stmt->init() != NULL) {
954 Visit(stmt->init());
955 }
956
957 increment_loop_depth();
958 // Emit the test at the bottom of the loop (even if empty).
959 __ jmp(&test);
960
ricow@chromium.org65fae842010-08-25 15:26:24 +0000961 __ bind(&stack_limit_hit);
962 StackCheckStub stack_stub;
963 __ CallStub(&stack_stub);
964 __ jmp(&stack_check_success);
965
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000966 __ bind(&body);
967 Visit(stmt->body());
968
969 __ bind(loop_statement.continue_target());
970
971 SetStatementPosition(stmt);
972 if (stmt->next() != NULL) {
973 Visit(stmt->next());
974 }
975
976 __ bind(&test);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000977 // Emit the statement position here as this is where the for
978 // statement code starts.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000979 SetStatementPosition(stmt);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000980
981 // Check stack before looping.
982 __ StackLimitCheck(&stack_limit_hit);
983 __ bind(&stack_check_success);
984
985 if (stmt->cond() != NULL) {
ricow@chromium.org65fae842010-08-25 15:26:24 +0000986 VisitForControl(stmt->cond(),
987 &body,
988 loop_statement.break_target(),
989 loop_statement.break_target());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000990 } else {
991 __ jmp(&body);
992 }
993
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000994 __ bind(loop_statement.break_target());
995 decrement_loop_depth();
996}
997
998
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000999void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1000 Comment cmnt(masm_, "[ TryCatchStatement");
1001 SetStatementPosition(stmt);
1002 // The try block adds a handler to the exception handler chain
1003 // before entering, and removes it again when exiting normally.
1004 // If an exception is thrown during execution of the try block,
1005 // control is passed to the handler, which also consumes the handler.
1006 // At this point, the exception is in a register, and store it in
1007 // the temporary local variable (prints as ".catch-var") before
1008 // executing the catch block. The catch block has been rewritten
1009 // to introduce a new scope to bind the catch variable and to remove
1010 // that scope again afterwards.
1011
1012 Label try_handler_setup, catch_entry, done;
1013 __ Call(&try_handler_setup);
1014 // Try handler code, exception in result register.
1015
1016 // Store exception in local .catch variable before executing catch block.
1017 {
1018 // The catch variable is *always* a variable proxy for a local variable.
1019 Variable* catch_var = stmt->catch_var()->AsVariableProxy()->AsVariable();
1020 ASSERT_NOT_NULL(catch_var);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001021 Slot* variable_slot = catch_var->AsSlot();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001022 ASSERT_NOT_NULL(variable_slot);
1023 ASSERT_EQ(Slot::LOCAL, variable_slot->type());
1024 StoreToFrameField(SlotOffset(variable_slot), result_register());
1025 }
1026
1027 Visit(stmt->catch_block());
1028 __ jmp(&done);
1029
1030 // Try block code. Sets up the exception handler chain.
1031 __ bind(&try_handler_setup);
1032 {
1033 TryCatch try_block(this, &catch_entry);
1034 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1035 Visit(stmt->try_block());
1036 __ PopTryHandler();
1037 }
1038 __ bind(&done);
1039}
1040
1041
1042void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1043 Comment cmnt(masm_, "[ TryFinallyStatement");
1044 SetStatementPosition(stmt);
1045 // Try finally is compiled by setting up a try-handler on the stack while
1046 // executing the try body, and removing it again afterwards.
1047 //
1048 // The try-finally construct can enter the finally block in three ways:
1049 // 1. By exiting the try-block normally. This removes the try-handler and
1050 // calls the finally block code before continuing.
1051 // 2. By exiting the try-block with a function-local control flow transfer
1052 // (break/continue/return). The site of the, e.g., break removes the
1053 // try handler and calls the finally block code before continuing
1054 // its outward control transfer.
1055 // 3. by exiting the try-block with a thrown exception.
1056 // This can happen in nested function calls. It traverses the try-handler
1057 // chain and consumes the try-handler entry before jumping to the
1058 // handler code. The handler code then calls the finally-block before
1059 // rethrowing the exception.
1060 //
1061 // The finally block must assume a return address on top of the stack
1062 // (or in the link register on ARM chips) and a value (return value or
1063 // exception) in the result register (rax/eax/r0), both of which must
1064 // be preserved. The return address isn't GC-safe, so it should be
1065 // cooked before GC.
1066 Label finally_entry;
1067 Label try_handler_setup;
1068
1069 // Setup the try-handler chain. Use a call to
1070 // Jump to try-handler setup and try-block code. Use call to put try-handler
1071 // address on stack.
1072 __ Call(&try_handler_setup);
1073 // Try handler code. Return address of call is pushed on handler stack.
1074 {
1075 // This code is only executed during stack-handler traversal when an
1076 // exception is thrown. The execption is in the result register, which
1077 // is retained by the finally block.
1078 // Call the finally block and then rethrow the exception.
1079 __ Call(&finally_entry);
1080 __ push(result_register());
1081 __ CallRuntime(Runtime::kReThrow, 1);
1082 }
1083
1084 __ bind(&finally_entry);
1085 {
1086 // Finally block implementation.
1087 Finally finally_block(this);
1088 EnterFinallyBlock();
1089 Visit(stmt->finally_block());
1090 ExitFinallyBlock(); // Return to the calling code.
1091 }
1092
1093 __ bind(&try_handler_setup);
1094 {
1095 // Setup try handler (stack pointer registers).
1096 TryFinally try_block(this, &finally_entry);
1097 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
1098 Visit(stmt->try_block());
1099 __ PopTryHandler();
1100 }
1101 // Execute the finally block on the way out.
1102 __ Call(&finally_entry);
1103}
1104
1105
1106void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1107#ifdef ENABLE_DEBUGGER_SUPPORT
1108 Comment cmnt(masm_, "[ DebuggerStatement");
1109 SetStatementPosition(stmt);
1110
ager@chromium.org5c838252010-02-19 08:53:10 +00001111 __ DebugBreak();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001112 // Ignore the return value.
1113#endif
1114}
1115
1116
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001117void FullCodeGenerator::VisitConditional(Conditional* expr) {
1118 Comment cmnt(masm_, "[ Conditional");
1119 Label true_case, false_case, done;
ricow@chromium.org65fae842010-08-25 15:26:24 +00001120 VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001121
1122 __ bind(&true_case);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001123 SetExpressionPosition(expr->then_expression(),
1124 expr->then_expression_position());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001125 Visit(expr->then_expression());
1126 // If control flow falls through Visit, jump to done.
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001127 if (!context()->IsTest()) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001128 __ jmp(&done);
1129 }
1130
1131 __ bind(&false_case);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001132 SetExpressionPosition(expr->else_expression(),
1133 expr->else_expression_position());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001134 Visit(expr->else_expression());
1135 // If control flow falls through Visit, merge it with true case here.
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001136 if (!context()->IsTest()) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001137 __ bind(&done);
1138 }
1139}
1140
1141
1142void FullCodeGenerator::VisitSlot(Slot* expr) {
1143 // Slots do not appear directly in the AST.
1144 UNREACHABLE();
1145}
1146
1147
1148void FullCodeGenerator::VisitLiteral(Literal* expr) {
1149 Comment cmnt(masm_, "[ Literal");
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001150 context()->Plug(expr->handle());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001151}
1152
1153
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001154void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1155 Comment cmnt(masm_, "[ FunctionLiteral");
1156
1157 // Build the function boilerplate and instantiate it.
1158 Handle<SharedFunctionInfo> function_info =
1159 Compiler::BuildFunctionInfo(expr, script(), this);
1160 if (HasStackOverflow()) return;
1161 EmitNewClosure(function_info);
1162}
1163
1164
1165void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
1166 SharedFunctionInfoLiteral* expr) {
1167 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
1168 EmitNewClosure(expr->shared_function_info());
1169}
1170
1171
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001172void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
1173 // Call runtime routine to allocate the catch extension object and
1174 // assign the exception value to the catch variable.
1175 Comment cmnt(masm_, "[ CatchExtensionObject");
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001176 VisitForStackValue(expr->key());
1177 VisitForStackValue(expr->value());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001178 // Create catch extension object.
1179 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001180 context()->Plug(result_register());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001181}
1182
1183
1184void FullCodeGenerator::VisitThrow(Throw* expr) {
1185 Comment cmnt(masm_, "[ Throw");
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001186 VisitForStackValue(expr->exception());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001187 __ CallRuntime(Runtime::kThrow, 1);
1188 // Never returns here.
1189}
1190
1191
ricow@chromium.org65fae842010-08-25 15:26:24 +00001192void FullCodeGenerator::VisitIncrementOperation(IncrementOperation* expr) {
1193 UNREACHABLE();
1194}
1195
1196
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001197int FullCodeGenerator::TryFinally::Exit(int stack_depth) {
1198 // The macros used here must preserve the result register.
1199 __ Drop(stack_depth);
1200 __ PopTryHandler();
1201 __ Call(finally_entry_);
1202 return 0;
1203}
1204
1205
1206int FullCodeGenerator::TryCatch::Exit(int stack_depth) {
1207 // The macros used here must preserve the result register.
1208 __ Drop(stack_depth);
1209 __ PopTryHandler();
1210 return 0;
1211}
1212
ricow@chromium.org65fae842010-08-25 15:26:24 +00001213
1214void FullCodeGenerator::EmitRegExpCloneResult(ZoneList<Expression*>* args) {
1215 ASSERT(args->length() == 1);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001216 VisitForStackValue(args->at(0));
ricow@chromium.org65fae842010-08-25 15:26:24 +00001217 __ CallRuntime(Runtime::kRegExpCloneResult, 1);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001218 context()->Plug(result_register());
ricow@chromium.org65fae842010-08-25 15:26:24 +00001219}
1220
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001221#undef __
1222
1223
1224} } // namespace v8::internal