Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 2220) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -27,10 +27,11 @@ |
#include "v8.h" |
-#include "macro-assembler.h" |
+ |
+#include "bootstrapper.h" |
+// #include "macro-assembler.h" |
+#include "codegen-inl.h" |
#include "register-allocator-inl.h" |
-#include "codegen-inl.h" |
-#include "codegen-x64-inl.h" |
// TEST |
#include "compiler.h" |
@@ -105,13 +106,12 @@ |
Handle<JSFunction> test_function = Compiler::Compile( |
Factory::NewStringFromAscii(CStrVector( |
"39;" |
- "(function(){return 43})();" |
- "42;" |
- // "function foo(x, y){return x;};" |
- "43;" |
- // "foo(2,3);" |
- "44;" |
- "(function(){return (function(){return 47})()})();")), |
+ "(function(){" |
+ "function foo(x, y){var w; y = x; x = w; w = y; y = x; return w;};" |
+ "function bar(x, y, zee){return zee;};" |
+ "foo(2,3);" |
+ "return foo(bar(foo(1,3), 42, 47), foo( -25.3, 2));" |
+ "})()")), |
Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), |
0, |
0, |
@@ -194,6 +194,44 @@ |
function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
function_return_is_shadowed_ = false; |
+ // TODO(X64): Add code to handle arguments object and context object. |
+ |
+ // Generate code to 'execute' declarations and initialize functions |
+ // (source elements). In case of an illegal redeclaration we need to |
+ // handle that instead of processing the declarations. |
+ if (scope_->HasIllegalRedeclaration()) { |
+ Comment cmnt(masm_, "[ illegal redeclarations"); |
+ scope_->VisitIllegalRedeclaration(this); |
+ } else { |
+ Comment cmnt(masm_, "[ declarations"); |
+ ProcessDeclarations(scope_->declarations()); |
+ // Bail out if a stack-overflow exception occurred when processing |
+ // declarations. |
+ if (HasStackOverflow()) return; |
+ } |
+ |
+ if (FLAG_trace) { |
+ frame_->CallRuntime(Runtime::kTraceEnter, 0); |
+ // Ignore the return value. |
+ } |
+ // CheckStack(); |
+ |
+ // Compile the body of the function in a vanilla state. Don't |
+ // bother compiling all the code if the scope has an illegal |
+ // redeclaration. |
+ if (!scope_->HasIllegalRedeclaration()) { |
+ Comment cmnt(masm_, "[ function body"); |
+#ifdef DEBUG |
+ bool is_builtin = Bootstrapper::IsActive(); |
+ bool should_trace = |
+ is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
+ if (should_trace) { |
+ frame_->CallRuntime(Runtime::kDebugTrace, 0); |
+ // Ignore the return value. |
+ } |
+#endif |
+ } |
+ |
VisitStatements(body); |
} |
// Adjust for function-level loop nesting. |
@@ -283,12 +321,83 @@ |
} |
-void CodeGenerator::VisitBlock(Block* a) { |
- UNIMPLEMENTED(); |
+void CodeGenerator::VisitBlock(Block* node) { |
+ ASSERT(!in_spilled_code()); |
+ Comment cmnt(masm_, "[ Block"); |
+ CodeForStatementPosition(node); |
+ node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
+ VisitStatements(node->statements()); |
+ if (node->break_target()->is_linked()) { |
+ node->break_target()->Bind(); |
+ } |
+ node->break_target()->Unuse(); |
} |
-void CodeGenerator::VisitDeclaration(Declaration* a) { |
- UNIMPLEMENTED(); |
+ |
+void CodeGenerator::VisitDeclaration(Declaration* node) { |
+ Comment cmnt(masm_, "[ Declaration"); |
+ CodeForStatementPosition(node); |
+ Variable* var = node->proxy()->var(); |
+ ASSERT(var != NULL); // must have been resolved |
+ Slot* slot = var->slot(); |
+ |
+ // If it was not possible to allocate the variable at compile time, |
+ // we need to "declare" it at runtime to make sure it actually |
+ // exists in the local context. |
+ if (slot != NULL && slot->type() == Slot::LOOKUP) { |
+ // Variables with a "LOOKUP" slot were introduced as non-locals |
+ // during variable resolution and must have mode DYNAMIC. |
+ ASSERT(var->is_dynamic()); |
+ // For now, just do a runtime call. Sync the virtual frame eagerly |
+ // so we can simply push the arguments into place. |
+ frame_->SyncRange(0, frame_->element_count() - 1); |
+ frame_->EmitPush(rsi); |
+ __ movq(kScratchRegister, var->name(), RelocInfo::EMBEDDED_OBJECT); |
+ frame_->EmitPush(kScratchRegister); |
+ // Declaration nodes are always introduced in one of two modes. |
+ ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); |
+ PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; |
+ frame_->EmitPush(Immediate(Smi::FromInt(attr))); |
+ // Push initial value, if any. |
+ // Note: For variables we must not push an initial value (such as |
+ // 'undefined') because we may have a (legal) redeclaration and we |
+ // must not destroy the current value. |
+ if (node->mode() == Variable::CONST) { |
+ __ movq(kScratchRegister, Factory::the_hole_value(), |
+ RelocInfo::EMBEDDED_OBJECT); |
+ frame_->EmitPush(kScratchRegister); |
+ } else if (node->fun() != NULL) { |
+ Load(node->fun()); |
+ } else { |
+ frame_->EmitPush(Immediate(Smi::FromInt(0))); // no initial value! |
+ } |
+ Result ignored = frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); |
+ // Ignore the return value (declarations are statements). |
+ return; |
+ } |
+ |
+ ASSERT(!var->is_global()); |
+ |
+ // If we have a function or a constant, we need to initialize the variable. |
+ Expression* val = NULL; |
+ if (node->mode() == Variable::CONST) { |
+ val = new Literal(Factory::the_hole_value()); |
+ } else { |
+ val = node->fun(); // NULL if we don't have a function |
+ } |
+ |
+ if (val != NULL) { |
+ { |
+ // Set the initial value. |
+ Reference target(this, node->proxy()); |
+ Load(val); |
+ target.SetValue(NOT_CONST_INIT); |
+ // The reference is removed from the stack (preserving TOS) when |
+ // it goes out of scope. |
+ } |
+ // Get rid of the assigned value (declarations are statements). |
+ frame_->Drop(); |
+ } |
} |