blob: 97987c27a80c7aae2c1349a12141fbcf171bad70 [file] [log] [blame]
Leon Clarked91b9f72010-01-27 17:25:45 +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"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010033#include "macro-assembler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010034#include "scopes.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000035#include "stub-cache.h"
36#include "debug.h"
Andrei Popescu402d9372010-02-26 13:31:12 +000037#include "liveedit.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000038
39namespace v8 {
40namespace internal {
41
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010042void 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
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100219void BreakableStatementChecker::VisitIncrementOperation(
220 IncrementOperation* expr) {
221 UNREACHABLE();
222}
223
224
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100225void 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
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100263void BreakableStatementChecker::VisitCompareToNull(CompareToNull* expr) {
264 Visit(expr->expression());
265}
266
267
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100268void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
269 Visit(expr->left());
270 Visit(expr->right());
271}
272
273
274void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
275}
276
277
Leon Clarked91b9f72010-01-27 17:25:45 +0000278#define __ ACCESS_MASM(masm())
279
Ben Murdochf87a2032010-10-22 12:50:53 +0100280bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
Andrei Popescu31002712010-02-23 13:46:05 +0000281 Handle<Script> script = info->script();
Leon Clarked91b9f72010-01-27 17:25:45 +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 }
Andrei Popescu31002712010-02-23 13:46:05 +0000286 CodeGenerator::MakeCodePrologue(info);
Leon Clarked91b9f72010-01-27 17:25:45 +0000287 const int kInitialBufferSize = 4 * KB;
288 MacroAssembler masm(NULL, kInitialBufferSize);
Andrei Popescu402d9372010-02-26 13:31:12 +0000289
Andrei Popescu31002712010-02-23 13:46:05 +0000290 FullCodeGenerator cgen(&masm);
Iain Merrick75681382010-08-19 15:07:18 +0100291 cgen.Generate(info);
Leon Clarked91b9f72010-01-27 17:25:45 +0000292 if (cgen.HasStackOverflow()) {
293 ASSERT(!Top::has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +0100294 return false;
Leon Clarked91b9f72010-01-27 17:25:45 +0000295 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100296
Leon Clarked91b9f72010-01-27 17:25:45 +0000297 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
Ben Murdochf87a2032010-10-22 12:50:53 +0100298 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
299 info->SetCode(code); // may be an empty handle.
300 return !code.is_null();
Leon Clarked91b9f72010-01-27 17:25:45 +0000301}
302
303
Steve Block59151502010-09-22 15:07:15 +0100304MemOperand FullCodeGenerator::ContextOperand(Register context, int index) {
305 return CodeGenerator::ContextOperand(context, index);
306}
307
308
Leon Clarked91b9f72010-01-27 17:25:45 +0000309int FullCodeGenerator::SlotOffset(Slot* slot) {
310 ASSERT(slot != NULL);
311 // Offset is negative because higher indexes are at lower addresses.
312 int offset = -slot->index() * kPointerSize;
313 // Adjust by a (parameter or local) base offset.
314 switch (slot->type()) {
315 case Slot::PARAMETER:
Andrei Popescu31002712010-02-23 13:46:05 +0000316 offset += (scope()->num_parameters() + 1) * kPointerSize;
Leon Clarked91b9f72010-01-27 17:25:45 +0000317 break;
318 case Slot::LOCAL:
319 offset += JavaScriptFrameConstants::kLocal0Offset;
320 break;
321 case Slot::CONTEXT:
322 case Slot::LOOKUP:
323 UNREACHABLE();
324 }
325 return offset;
326}
327
328
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100329bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100330 // Inline smi case inside loops, but not division and modulo which
331 // are too complicated and take up too much space.
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100332 if (op == Token::DIV ||op == Token::MOD) return false;
333 if (FLAG_always_inline_smi_code) return true;
334 return loop_depth_ > 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100335}
336
337
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100338void FullCodeGenerator::EffectContext::Plug(Register reg) const {
339}
340
341
342void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
343 // Move value into place.
344 __ Move(result_register(), reg);
345}
346
347
348void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
349 // Move value into place.
350 __ push(reg);
351}
352
353
354void FullCodeGenerator::TestContext::Plug(Register reg) const {
355 // For simplicity we always test the accumulator register.
356 __ Move(result_register(), reg);
357 codegen()->DoTest(true_label_, false_label_, fall_through_);
358}
359
360
361void FullCodeGenerator::EffectContext::PlugTOS() const {
362 __ Drop(1);
363}
364
365
366void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
367 __ pop(result_register());
368}
369
370
371void FullCodeGenerator::StackValueContext::PlugTOS() const {
372}
373
374
375void FullCodeGenerator::TestContext::PlugTOS() const {
376 // For simplicity we always test the accumulator register.
377 __ pop(result_register());
378 codegen()->DoTest(true_label_, false_label_, fall_through_);
379}
380
381
382void FullCodeGenerator::EffectContext::PrepareTest(
383 Label* materialize_true,
384 Label* materialize_false,
385 Label** if_true,
386 Label** if_false,
387 Label** fall_through) const {
388 // In an effect context, the true and the false case branch to the
389 // same label.
390 *if_true = *if_false = *fall_through = materialize_true;
391}
392
393
394void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
395 Label* materialize_true,
396 Label* materialize_false,
397 Label** if_true,
398 Label** if_false,
399 Label** fall_through) const {
400 *if_true = *fall_through = materialize_true;
401 *if_false = materialize_false;
402}
403
404
405void FullCodeGenerator::StackValueContext::PrepareTest(
406 Label* materialize_true,
407 Label* materialize_false,
408 Label** if_true,
409 Label** if_false,
410 Label** fall_through) const {
411 *if_true = *fall_through = materialize_true;
412 *if_false = materialize_false;
413}
414
415
416void FullCodeGenerator::TestContext::PrepareTest(
417 Label* materialize_true,
418 Label* materialize_false,
419 Label** if_true,
420 Label** if_false,
421 Label** fall_through) const {
422 *if_true = true_label_;
423 *if_false = false_label_;
424 *fall_through = fall_through_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100425}
426
427
Leon Clarked91b9f72010-01-27 17:25:45 +0000428void FullCodeGenerator::VisitDeclarations(
429 ZoneList<Declaration*>* declarations) {
430 int length = declarations->length();
431 int globals = 0;
432 for (int i = 0; i < length; i++) {
433 Declaration* decl = declarations->at(i);
434 Variable* var = decl->proxy()->var();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100435 Slot* slot = var->AsSlot();
Leon Clarked91b9f72010-01-27 17:25:45 +0000436
437 // If it was not possible to allocate the variable at compile
438 // time, we need to "declare" it at runtime to make sure it
439 // actually exists in the local context.
440 if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
441 VisitDeclaration(decl);
442 } else {
443 // Count global variables and functions for later processing
444 globals++;
445 }
446 }
447
448 // Compute array of global variable and function declarations.
449 // Do nothing in case of no declared global functions or variables.
450 if (globals > 0) {
451 Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED);
452 for (int j = 0, i = 0; i < length; i++) {
453 Declaration* decl = declarations->at(i);
454 Variable* var = decl->proxy()->var();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100455 Slot* slot = var->AsSlot();
Leon Clarked91b9f72010-01-27 17:25:45 +0000456
457 if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) {
458 array->set(j++, *(var->name()));
459 if (decl->fun() == NULL) {
460 if (var->mode() == Variable::CONST) {
461 // In case this is const property use the hole.
462 array->set_the_hole(j++);
463 } else {
464 array->set_undefined(j++);
465 }
466 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100467 Handle<SharedFunctionInfo> function =
Ben Murdochf87a2032010-10-22 12:50:53 +0100468 Compiler::BuildFunctionInfo(decl->fun(), script());
Leon Clarked91b9f72010-01-27 17:25:45 +0000469 // Check for stack-overflow exception.
Ben Murdochf87a2032010-10-22 12:50:53 +0100470 if (function.is_null()) {
471 SetStackOverflow();
472 return;
473 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000474 array->set(j++, *function);
475 }
476 }
477 }
478 // Invoke the platform-dependent code generator to do the actual
479 // declaration the global variables and functions.
480 DeclareGlobals(array);
481 }
482}
483
484
485void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
486 if (FLAG_debug_info) {
487 CodeGenerator::RecordPositions(masm_, fun->start_position());
488 }
489}
490
491
492void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
493 if (FLAG_debug_info) {
Ben Murdochbb769b22010-08-11 14:56:33 +0100494 CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
Leon Clarked91b9f72010-01-27 17:25:45 +0000495 }
496}
497
498
499void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
500 if (FLAG_debug_info) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100501#ifdef ENABLE_DEBUGGER_SUPPORT
502 if (!Debugger::IsDebuggerActive()) {
503 CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
504 } else {
505 // Check if the statement will be breakable without adding a debug break
506 // slot.
507 BreakableStatementChecker checker;
508 checker.Check(stmt);
509 // Record the statement position right here if the statement is not
510 // breakable. For breakable statements the actual recording of the
511 // position will be postponed to the breakable code (typically an IC).
512 bool position_recorded = CodeGenerator::RecordPositions(
513 masm_, stmt->statement_pos(), !checker.is_breakable());
514 // If the position recording did record a new position generate a debug
515 // break slot to make the statement breakable.
516 if (position_recorded) {
517 Debug::GenerateSlot(masm_);
518 }
519 }
520#else
Leon Clarked91b9f72010-01-27 17:25:45 +0000521 CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100522#endif
523 }
524}
525
526
527void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
528 if (FLAG_debug_info) {
529#ifdef ENABLE_DEBUGGER_SUPPORT
530 if (!Debugger::IsDebuggerActive()) {
531 CodeGenerator::RecordPositions(masm_, pos);
532 } else {
533 // Check if the expression will be breakable without adding a debug break
534 // slot.
535 BreakableStatementChecker checker;
536 checker.Check(expr);
537 // Record a statement position right here if the expression is not
538 // breakable. For breakable expressions the actual recording of the
539 // position will be postponed to the breakable code (typically an IC).
540 // NOTE this will record a statement position for something which might
541 // not be a statement. As stepping in the debugger will only stop at
542 // statement positions this is used for e.g. the condition expression of
543 // a do while loop.
544 bool position_recorded = CodeGenerator::RecordPositions(
545 masm_, pos, !checker.is_breakable());
546 // If the position recording did record a new position generate a debug
547 // break slot to make the statement breakable.
548 if (position_recorded) {
549 Debug::GenerateSlot(masm_);
550 }
551 }
552#else
553 CodeGenerator::RecordPositions(masm_, pos);
554#endif
Leon Clarked91b9f72010-01-27 17:25:45 +0000555 }
556}
557
558
559void FullCodeGenerator::SetStatementPosition(int pos) {
560 if (FLAG_debug_info) {
561 CodeGenerator::RecordPositions(masm_, pos);
562 }
563}
564
565
566void FullCodeGenerator::SetSourcePosition(int pos) {
567 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) {
568 masm_->RecordPosition(pos);
569 }
570}
571
572
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100573// Lookup table for code generators for special runtime calls which are
574// generated inline.
575#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
576 &FullCodeGenerator::Emit##Name,
Steve Block791712a2010-08-27 10:21:07 +0100577
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100578const FullCodeGenerator::InlineFunctionGenerator
579 FullCodeGenerator::kInlineFunctionGenerators[] = {
580 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
581 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
582 };
583#undef INLINE_FUNCTION_GENERATOR_ADDRESS
584
585
586FullCodeGenerator::InlineFunctionGenerator
587 FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
588 return kInlineFunctionGenerators[
589 static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
590}
591
592
593void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
594 ZoneList<Expression*>* args = node->arguments();
595 Handle<String> name = node->name();
596 Runtime::Function* function = node->function();
597 ASSERT(function != NULL);
598 ASSERT(function->intrinsic_type == Runtime::INLINE);
599 InlineFunctionGenerator generator =
600 FindInlineFunctionGenerator(function->function_id);
601 ASSERT(generator != NULL);
602 ((*this).*(generator))(args);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100603}
604
605
606void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
607 Comment cmnt(masm_, "[ BinaryOperation");
608 Token::Value op = expr->op();
609 Expression* left = expr->left();
610 Expression* right = expr->right();
611
612 OverwriteMode mode = NO_OVERWRITE;
613 if (left->ResultOverwriteAllowed()) {
614 mode = OVERWRITE_LEFT;
615 } else if (right->ResultOverwriteAllowed()) {
616 mode = OVERWRITE_RIGHT;
617 }
618
619 switch (op) {
620 case Token::COMMA:
621 VisitForEffect(left);
622 Visit(right);
623 break;
624
625 case Token::OR:
626 case Token::AND:
627 EmitLogicalOperation(expr);
628 break;
629
630 case Token::ADD:
631 case Token::SUB:
632 case Token::DIV:
633 case Token::MOD:
634 case Token::MUL:
635 case Token::BIT_OR:
636 case Token::BIT_AND:
637 case Token::BIT_XOR:
638 case Token::SHL:
639 case Token::SHR:
640 case Token::SAR: {
641 // Figure out if either of the operands is a constant.
642 ConstantOperand constant = ShouldInlineSmiCase(op)
643 ? GetConstantOperand(op, left, right)
644 : kNoConstants;
645
646 // Load only the operands that we need to materialize.
647 if (constant == kNoConstants) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100648 VisitForStackValue(left);
649 VisitForAccumulatorValue(right);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100650 } else if (constant == kRightConstant) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100651 VisitForAccumulatorValue(left);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100652 } else {
653 ASSERT(constant == kLeftConstant);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100654 VisitForAccumulatorValue(right);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100655 }
656
657 SetSourcePosition(expr->position());
658 if (ShouldInlineSmiCase(op)) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100659 EmitInlineSmiBinaryOp(expr, op, mode, left, right, constant);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100660 } else {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100661 EmitBinaryOp(op, mode);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100662 }
663 break;
664 }
665
666 default:
667 UNREACHABLE();
668 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100669}
670
671
Leon Clarked91b9f72010-01-27 17:25:45 +0000672void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
673 Label eval_right, done;
674
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100675 context()->EmitLogicalLeft(expr, &eval_right, &done);
Leon Clarked91b9f72010-01-27 17:25:45 +0000676
677 __ bind(&eval_right);
678 Visit(expr->right());
679
680 __ bind(&done);
681}
682
683
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100684void FullCodeGenerator::EffectContext::EmitLogicalLeft(BinaryOperation* expr,
685 Label* eval_right,
686 Label* done) const {
687 if (expr->op() == Token::OR) {
688 codegen()->VisitForControl(expr->left(), done, eval_right, eval_right);
689 } else {
690 ASSERT(expr->op() == Token::AND);
691 codegen()->VisitForControl(expr->left(), eval_right, done, eval_right);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100692 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100693}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100694
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100695
696void FullCodeGenerator::AccumulatorValueContext::EmitLogicalLeft(
697 BinaryOperation* expr,
698 Label* eval_right,
699 Label* done) const {
700 codegen()->Visit(expr->left());
701 // We want the value in the accumulator for the test, and on the stack in case
702 // we need it.
703 __ push(result_register());
704 Label discard, restore;
705 if (expr->op() == Token::OR) {
706 codegen()->DoTest(&restore, &discard, &restore);
707 } else {
708 ASSERT(expr->op() == Token::AND);
709 codegen()->DoTest(&discard, &restore, &restore);
710 }
711 __ bind(&restore);
712 __ pop(result_register());
713 __ jmp(done);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100714 __ bind(&discard);
715 __ Drop(1);
716}
717
718
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100719void FullCodeGenerator::StackValueContext::EmitLogicalLeft(
720 BinaryOperation* expr,
721 Label* eval_right,
722 Label* done) const {
723 codegen()->VisitForAccumulatorValue(expr->left());
724 // We want the value in the accumulator for the test, and on the stack in case
725 // we need it.
726 __ push(result_register());
727 Label discard;
728 if (expr->op() == Token::OR) {
729 codegen()->DoTest(done, &discard, &discard);
730 } else {
731 ASSERT(expr->op() == Token::AND);
732 codegen()->DoTest(&discard, done, &discard);
733 }
734 __ bind(&discard);
735 __ Drop(1);
736}
737
738
739void FullCodeGenerator::TestContext::EmitLogicalLeft(BinaryOperation* expr,
740 Label* eval_right,
741 Label* done) const {
742 if (expr->op() == Token::OR) {
743 codegen()->VisitForControl(expr->left(),
744 true_label_, eval_right, eval_right);
745 } else {
746 ASSERT(expr->op() == Token::AND);
747 codegen()->VisitForControl(expr->left(),
748 eval_right, false_label_, eval_right);
749 }
750}
751
752
Leon Clarked91b9f72010-01-27 17:25:45 +0000753void FullCodeGenerator::VisitBlock(Block* stmt) {
754 Comment cmnt(masm_, "[ Block");
755 Breakable nested_statement(this, stmt);
756 SetStatementPosition(stmt);
757 VisitStatements(stmt->statements());
758 __ bind(nested_statement.break_target());
759}
760
761
762void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
763 Comment cmnt(masm_, "[ ExpressionStatement");
764 SetStatementPosition(stmt);
765 VisitForEffect(stmt->expression());
766}
767
768
769void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
770 Comment cmnt(masm_, "[ EmptyStatement");
771 SetStatementPosition(stmt);
772}
773
774
775void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
776 Comment cmnt(masm_, "[ IfStatement");
777 SetStatementPosition(stmt);
778 Label then_part, else_part, done;
779
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100780 if (stmt->HasElseStatement()) {
781 VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
782 __ bind(&then_part);
783 Visit(stmt->then_statement());
784 __ jmp(&done);
Leon Clarked91b9f72010-01-27 17:25:45 +0000785
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100786 __ bind(&else_part);
787 Visit(stmt->else_statement());
788 } else {
789 VisitForControl(stmt->condition(), &then_part, &done, &then_part);
790 __ bind(&then_part);
791 Visit(stmt->then_statement());
792 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000793 __ bind(&done);
794}
795
796
797void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
798 Comment cmnt(masm_, "[ ContinueStatement");
799 SetStatementPosition(stmt);
800 NestedStatement* current = nesting_stack_;
801 int stack_depth = 0;
802 while (!current->IsContinueTarget(stmt->target())) {
803 stack_depth = current->Exit(stack_depth);
804 current = current->outer();
805 }
806 __ Drop(stack_depth);
807
808 Iteration* loop = current->AsIteration();
809 __ jmp(loop->continue_target());
810}
811
812
813void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
814 Comment cmnt(masm_, "[ BreakStatement");
815 SetStatementPosition(stmt);
816 NestedStatement* current = nesting_stack_;
817 int stack_depth = 0;
818 while (!current->IsBreakTarget(stmt->target())) {
819 stack_depth = current->Exit(stack_depth);
820 current = current->outer();
821 }
822 __ Drop(stack_depth);
823
824 Breakable* target = current->AsBreakable();
825 __ jmp(target->break_target());
826}
827
828
829void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
830 Comment cmnt(masm_, "[ ReturnStatement");
831 SetStatementPosition(stmt);
832 Expression* expr = stmt->expression();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100833 VisitForAccumulatorValue(expr);
Leon Clarked91b9f72010-01-27 17:25:45 +0000834
835 // Exit all nested statements.
836 NestedStatement* current = nesting_stack_;
837 int stack_depth = 0;
838 while (current != NULL) {
839 stack_depth = current->Exit(stack_depth);
840 current = current->outer();
841 }
842 __ Drop(stack_depth);
843
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100844 EmitReturnSequence();
Leon Clarked91b9f72010-01-27 17:25:45 +0000845}
846
847
848void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
849 Comment cmnt(masm_, "[ WithEnterStatement");
850 SetStatementPosition(stmt);
851
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100852 VisitForStackValue(stmt->expression());
Leon Clarked91b9f72010-01-27 17:25:45 +0000853 if (stmt->is_catch_block()) {
854 __ CallRuntime(Runtime::kPushCatchContext, 1);
855 } else {
856 __ CallRuntime(Runtime::kPushContext, 1);
857 }
858 // Both runtime calls return the new context in both the context and the
859 // result registers.
860
861 // Update local stack frame context field.
862 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
863}
864
865
866void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
867 Comment cmnt(masm_, "[ WithExitStatement");
868 SetStatementPosition(stmt);
869
870 // Pop context.
871 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
872 // Update local stack frame context field.
873 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
874}
875
876
Leon Clarked91b9f72010-01-27 17:25:45 +0000877void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
878 Comment cmnt(masm_, "[ DoWhileStatement");
879 SetStatementPosition(stmt);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100880 Label body, stack_limit_hit, stack_check_success, done;
Leon Clarked91b9f72010-01-27 17:25:45 +0000881
882 Iteration loop_statement(this, stmt);
883 increment_loop_depth();
884
885 __ bind(&body);
886 Visit(stmt->body());
887
888 // Check stack before looping.
889 __ StackLimitCheck(&stack_limit_hit);
890 __ bind(&stack_check_success);
891
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100892 // Record the position of the do while condition and make sure it is
893 // possible to break on the condition.
Leon Clarked91b9f72010-01-27 17:25:45 +0000894 __ bind(loop_statement.continue_target());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100895 SetExpressionPosition(stmt->cond(), stmt->condition_position());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100896 VisitForControl(stmt->cond(),
897 &body,
898 loop_statement.break_target(),
899 loop_statement.break_target());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100900
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100901 __ bind(loop_statement.break_target());
902 __ jmp(&done);
Leon Clarked91b9f72010-01-27 17:25:45 +0000903
904 __ bind(&stack_limit_hit);
905 StackCheckStub stack_stub;
906 __ CallStub(&stack_stub);
907 __ jmp(&stack_check_success);
908
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100909 __ bind(&done);
Leon Clarked91b9f72010-01-27 17:25:45 +0000910 decrement_loop_depth();
911}
912
913
914void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
915 Comment cmnt(masm_, "[ WhileStatement");
Iain Merrick9ac36c92010-09-13 15:29:50 +0100916 Label body, stack_limit_hit, stack_check_success, done;
Leon Clarked91b9f72010-01-27 17:25:45 +0000917
918 Iteration loop_statement(this, stmt);
919 increment_loop_depth();
920
921 // Emit the test at the bottom of the loop.
922 __ jmp(loop_statement.continue_target());
923
924 __ bind(&body);
925 Visit(stmt->body());
Leon Clarked91b9f72010-01-27 17:25:45 +0000926 __ bind(loop_statement.continue_target());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100927
928 // Emit the statement position here as this is where the while
929 // statement code starts.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100930 SetStatementPosition(stmt);
Leon Clarkef7060e22010-06-03 12:02:55 +0100931
Leon Clarked91b9f72010-01-27 17:25:45 +0000932 // Check stack before looping.
933 __ StackLimitCheck(&stack_limit_hit);
934 __ bind(&stack_check_success);
935
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100936 VisitForControl(stmt->cond(),
937 &body,
938 loop_statement.break_target(),
939 loop_statement.break_target());
Leon Clarked91b9f72010-01-27 17:25:45 +0000940
941 __ bind(loop_statement.break_target());
Iain Merrick9ac36c92010-09-13 15:29:50 +0100942 __ jmp(&done);
943
944 __ bind(&stack_limit_hit);
945 StackCheckStub stack_stub;
946 __ CallStub(&stack_stub);
947 __ jmp(&stack_check_success);
948
949 __ bind(&done);
Leon Clarked91b9f72010-01-27 17:25:45 +0000950 decrement_loop_depth();
951}
952
953
954void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
955 Comment cmnt(masm_, "[ ForStatement");
Leon Clarked91b9f72010-01-27 17:25:45 +0000956 Label test, body, stack_limit_hit, stack_check_success;
957
958 Iteration loop_statement(this, stmt);
959 if (stmt->init() != NULL) {
960 Visit(stmt->init());
961 }
962
963 increment_loop_depth();
964 // Emit the test at the bottom of the loop (even if empty).
965 __ jmp(&test);
966
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100967 __ bind(&stack_limit_hit);
968 StackCheckStub stack_stub;
969 __ CallStub(&stack_stub);
970 __ jmp(&stack_check_success);
971
Leon Clarked91b9f72010-01-27 17:25:45 +0000972 __ bind(&body);
973 Visit(stmt->body());
974
975 __ bind(loop_statement.continue_target());
976
977 SetStatementPosition(stmt);
978 if (stmt->next() != NULL) {
979 Visit(stmt->next());
980 }
981
982 __ bind(&test);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100983 // Emit the statement position here as this is where the for
984 // statement code starts.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100985 SetStatementPosition(stmt);
Leon Clarked91b9f72010-01-27 17:25:45 +0000986
987 // Check stack before looping.
988 __ StackLimitCheck(&stack_limit_hit);
989 __ bind(&stack_check_success);
990
991 if (stmt->cond() != NULL) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100992 VisitForControl(stmt->cond(),
993 &body,
994 loop_statement.break_target(),
995 loop_statement.break_target());
Leon Clarked91b9f72010-01-27 17:25:45 +0000996 } else {
997 __ jmp(&body);
998 }
999
Leon Clarked91b9f72010-01-27 17:25:45 +00001000 __ bind(loop_statement.break_target());
1001 decrement_loop_depth();
1002}
1003
1004
Leon Clarked91b9f72010-01-27 17:25:45 +00001005void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1006 Comment cmnt(masm_, "[ TryCatchStatement");
1007 SetStatementPosition(stmt);
1008 // The try block adds a handler to the exception handler chain
1009 // before entering, and removes it again when exiting normally.
1010 // If an exception is thrown during execution of the try block,
1011 // control is passed to the handler, which also consumes the handler.
1012 // At this point, the exception is in a register, and store it in
1013 // the temporary local variable (prints as ".catch-var") before
1014 // executing the catch block. The catch block has been rewritten
1015 // to introduce a new scope to bind the catch variable and to remove
1016 // that scope again afterwards.
1017
1018 Label try_handler_setup, catch_entry, done;
1019 __ Call(&try_handler_setup);
1020 // Try handler code, exception in result register.
1021
1022 // Store exception in local .catch variable before executing catch block.
1023 {
1024 // The catch variable is *always* a variable proxy for a local variable.
1025 Variable* catch_var = stmt->catch_var()->AsVariableProxy()->AsVariable();
1026 ASSERT_NOT_NULL(catch_var);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001027 Slot* variable_slot = catch_var->AsSlot();
Leon Clarked91b9f72010-01-27 17:25:45 +00001028 ASSERT_NOT_NULL(variable_slot);
1029 ASSERT_EQ(Slot::LOCAL, variable_slot->type());
1030 StoreToFrameField(SlotOffset(variable_slot), result_register());
1031 }
1032
1033 Visit(stmt->catch_block());
1034 __ jmp(&done);
1035
1036 // Try block code. Sets up the exception handler chain.
1037 __ bind(&try_handler_setup);
1038 {
1039 TryCatch try_block(this, &catch_entry);
1040 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1041 Visit(stmt->try_block());
1042 __ PopTryHandler();
1043 }
1044 __ bind(&done);
1045}
1046
1047
1048void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1049 Comment cmnt(masm_, "[ TryFinallyStatement");
1050 SetStatementPosition(stmt);
1051 // Try finally is compiled by setting up a try-handler on the stack while
1052 // executing the try body, and removing it again afterwards.
1053 //
1054 // The try-finally construct can enter the finally block in three ways:
1055 // 1. By exiting the try-block normally. This removes the try-handler and
1056 // calls the finally block code before continuing.
1057 // 2. By exiting the try-block with a function-local control flow transfer
1058 // (break/continue/return). The site of the, e.g., break removes the
1059 // try handler and calls the finally block code before continuing
1060 // its outward control transfer.
1061 // 3. by exiting the try-block with a thrown exception.
1062 // This can happen in nested function calls. It traverses the try-handler
1063 // chain and consumes the try-handler entry before jumping to the
1064 // handler code. The handler code then calls the finally-block before
1065 // rethrowing the exception.
1066 //
1067 // The finally block must assume a return address on top of the stack
1068 // (or in the link register on ARM chips) and a value (return value or
1069 // exception) in the result register (rax/eax/r0), both of which must
1070 // be preserved. The return address isn't GC-safe, so it should be
1071 // cooked before GC.
1072 Label finally_entry;
1073 Label try_handler_setup;
1074
1075 // Setup the try-handler chain. Use a call to
1076 // Jump to try-handler setup and try-block code. Use call to put try-handler
1077 // address on stack.
1078 __ Call(&try_handler_setup);
1079 // Try handler code. Return address of call is pushed on handler stack.
1080 {
1081 // This code is only executed during stack-handler traversal when an
1082 // exception is thrown. The execption is in the result register, which
1083 // is retained by the finally block.
1084 // Call the finally block and then rethrow the exception.
1085 __ Call(&finally_entry);
1086 __ push(result_register());
1087 __ CallRuntime(Runtime::kReThrow, 1);
1088 }
1089
1090 __ bind(&finally_entry);
1091 {
1092 // Finally block implementation.
1093 Finally finally_block(this);
1094 EnterFinallyBlock();
1095 Visit(stmt->finally_block());
1096 ExitFinallyBlock(); // Return to the calling code.
1097 }
1098
1099 __ bind(&try_handler_setup);
1100 {
1101 // Setup try handler (stack pointer registers).
1102 TryFinally try_block(this, &finally_entry);
1103 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
1104 Visit(stmt->try_block());
1105 __ PopTryHandler();
1106 }
1107 // Execute the finally block on the way out.
1108 __ Call(&finally_entry);
1109}
1110
1111
1112void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1113#ifdef ENABLE_DEBUGGER_SUPPORT
1114 Comment cmnt(masm_, "[ DebuggerStatement");
1115 SetStatementPosition(stmt);
Leon Clarke4515c472010-02-03 11:58:03 +00001116
Andrei Popescu402d9372010-02-26 13:31:12 +00001117 __ DebugBreak();
Leon Clarked91b9f72010-01-27 17:25:45 +00001118 // Ignore the return value.
1119#endif
1120}
1121
1122
Leon Clarked91b9f72010-01-27 17:25:45 +00001123void FullCodeGenerator::VisitConditional(Conditional* expr) {
1124 Comment cmnt(masm_, "[ Conditional");
1125 Label true_case, false_case, done;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001126 VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
Leon Clarked91b9f72010-01-27 17:25:45 +00001127
1128 __ bind(&true_case);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001129 SetExpressionPosition(expr->then_expression(),
1130 expr->then_expression_position());
Ben Murdochf87a2032010-10-22 12:50:53 +01001131 if (context()->IsTest()) {
1132 const TestContext* for_test = TestContext::cast(context());
1133 VisitForControl(expr->then_expression(),
1134 for_test->true_label(),
1135 for_test->false_label(),
1136 NULL);
1137 } else {
1138 Visit(expr->then_expression());
Leon Clarked91b9f72010-01-27 17:25:45 +00001139 __ jmp(&done);
1140 }
1141
1142 __ bind(&false_case);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001143 SetExpressionPosition(expr->else_expression(),
1144 expr->else_expression_position());
Leon Clarked91b9f72010-01-27 17:25:45 +00001145 Visit(expr->else_expression());
1146 // If control flow falls through Visit, merge it with true case here.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001147 if (!context()->IsTest()) {
Leon Clarked91b9f72010-01-27 17:25:45 +00001148 __ bind(&done);
1149 }
1150}
1151
1152
1153void FullCodeGenerator::VisitSlot(Slot* expr) {
1154 // Slots do not appear directly in the AST.
1155 UNREACHABLE();
1156}
1157
1158
1159void FullCodeGenerator::VisitLiteral(Literal* expr) {
1160 Comment cmnt(masm_, "[ Literal");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001161 context()->Plug(expr->handle());
Leon Clarked91b9f72010-01-27 17:25:45 +00001162}
1163
1164
Leon Clarkef7060e22010-06-03 12:02:55 +01001165void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1166 Comment cmnt(masm_, "[ FunctionLiteral");
1167
1168 // Build the function boilerplate and instantiate it.
1169 Handle<SharedFunctionInfo> function_info =
Ben Murdochf87a2032010-10-22 12:50:53 +01001170 Compiler::BuildFunctionInfo(expr, script());
1171 if (function_info.is_null()) {
1172 SetStackOverflow();
1173 return;
1174 }
Leon Clarkef7060e22010-06-03 12:02:55 +01001175 EmitNewClosure(function_info);
1176}
1177
1178
1179void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
1180 SharedFunctionInfoLiteral* expr) {
1181 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
1182 EmitNewClosure(expr->shared_function_info());
1183}
1184
1185
Leon Clarked91b9f72010-01-27 17:25:45 +00001186void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
1187 // Call runtime routine to allocate the catch extension object and
1188 // assign the exception value to the catch variable.
1189 Comment cmnt(masm_, "[ CatchExtensionObject");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001190 VisitForStackValue(expr->key());
1191 VisitForStackValue(expr->value());
Leon Clarked91b9f72010-01-27 17:25:45 +00001192 // Create catch extension object.
1193 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001194 context()->Plug(result_register());
Leon Clarked91b9f72010-01-27 17:25:45 +00001195}
1196
1197
1198void FullCodeGenerator::VisitThrow(Throw* expr) {
1199 Comment cmnt(masm_, "[ Throw");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001200 VisitForStackValue(expr->exception());
Leon Clarked91b9f72010-01-27 17:25:45 +00001201 __ CallRuntime(Runtime::kThrow, 1);
1202 // Never returns here.
1203}
1204
1205
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001206void FullCodeGenerator::VisitIncrementOperation(IncrementOperation* expr) {
1207 UNREACHABLE();
1208}
1209
1210
Leon Clarked91b9f72010-01-27 17:25:45 +00001211int FullCodeGenerator::TryFinally::Exit(int stack_depth) {
1212 // The macros used here must preserve the result register.
1213 __ Drop(stack_depth);
1214 __ PopTryHandler();
1215 __ Call(finally_entry_);
1216 return 0;
1217}
1218
1219
1220int FullCodeGenerator::TryCatch::Exit(int stack_depth) {
1221 // The macros used here must preserve the result register.
1222 __ Drop(stack_depth);
1223 __ PopTryHandler();
1224 return 0;
1225}
1226
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001227
1228void FullCodeGenerator::EmitRegExpCloneResult(ZoneList<Expression*>* args) {
1229 ASSERT(args->length() == 1);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001230 VisitForStackValue(args->at(0));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001231 __ CallRuntime(Runtime::kRegExpCloneResult, 1);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001232 context()->Plug(result_register());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001233}
1234
Leon Clarked91b9f72010-01-27 17:25:45 +00001235#undef __
1236
1237
1238} } // namespace v8::internal