Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 2176) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -30,6 +30,8 @@ |
#include "macro-assembler.h" |
#include "register-allocator-inl.h" |
#include "codegen.h" |
+// TEST |
+#include "compiler.h" |
namespace v8 { |
namespace internal { |
@@ -97,84 +99,119 @@ |
} |
void CodeGenerator::TestCodeGenerator() { |
- // Generate code. |
- ZoneScope zone_scope(DELETE_ON_EXIT); |
- const int initial_buffer_size = 4 * KB; |
- CodeGenerator cgen(initial_buffer_size, NULL, false); |
- CodeGeneratorScope scope(&cgen); |
- Scope dummy_scope; |
- cgen.scope_ = &dummy_scope; |
- cgen.GenCode(NULL); |
+ // Compile a function from a string, and run it. |
+ Handle<JSFunction> test_function = Compiler::Compile( |
+ Factory::NewStringFromAscii(CStrVector("42")), |
+ Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), |
+ 0, |
+ 0, |
+ NULL, |
+ NULL); |
- CodeDesc desc; |
- cgen.masm()->GetCode(&desc); |
+ Code* code_object = test_function->code(); // Local for debugging ease. |
+ USE(code_object); |
+ |
+ // Create a dummy function and context. |
+ Handle<JSFunction> bridge = |
+ Factory::NewFunction(Factory::empty_symbol(), Factory::undefined_value()); |
+ Handle<Context> context = |
+ Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge); |
+ |
+ test_function = Factory::NewFunctionFromBoilerplate( |
+ test_function, |
+ context); |
+ |
+ bool pending_exceptions; |
+ Handle<Object> result = |
+ Execution::Call(test_function, |
+ Handle<Object>::cast(test_function), |
+ 0, |
+ NULL, |
+ &pending_exceptions); |
+ CHECK(result->IsSmi()); |
+ CHECK_EQ(42, Smi::cast(*result)->value()); |
} |
void CodeGenerator::GenCode(FunctionLiteral* function) { |
- if (function != NULL) { |
- CodeForFunctionPosition(function); |
- // ASSERT(scope_ == NULL); |
- // scope_ = function->scope(); |
- __ int3(); // UNIMPLEMENTED |
- } else { |
- // GenCode Implementation under construction. Run by TestCodeGenerator |
- // with a == NULL. |
- // Everything guarded by if (function) should be run, unguarded, |
- // once testing is over. |
- // Record the position for debugging purposes. |
- if (function) { |
- CodeForFunctionPosition(function); |
- } |
- // ZoneList<Statement*>* body = fun->body(); |
+ // Record the position for debugging purposes. |
+ CodeForFunctionPosition(function); |
+ // ZoneList<Statement*>* body = fun->body(); |
- // Initialize state. |
- // While testing, scope is set in cgen before calling GenCode(). |
- if (function) { |
- ASSERT(scope_ == NULL); |
- scope_ = function->scope(); |
- } |
- ASSERT(allocator_ == NULL); |
- RegisterAllocator register_allocator(this); |
- allocator_ = ®ister_allocator; |
- ASSERT(frame_ == NULL); |
- frame_ = new VirtualFrame(); |
- set_in_spilled_code(false); |
+ // Initialize state. |
+ ASSERT(scope_ == NULL); |
+ scope_ = function->scope(); |
+ ASSERT(allocator_ == NULL); |
+ RegisterAllocator register_allocator(this); |
+ allocator_ = ®ister_allocator; |
+ ASSERT(frame_ == NULL); |
+ frame_ = new VirtualFrame(); |
+ set_in_spilled_code(false); |
- // Adjust for function-level loop nesting. |
- // loop_nesting_ += fun->loop_nesting(); |
+ // Adjust for function-level loop nesting. |
+ loop_nesting_ += function->loop_nesting(); |
- JumpTarget::set_compiling_deferred_code(false); |
+ JumpTarget::set_compiling_deferred_code(false); |
#ifdef DEBUG |
- if (strlen(FLAG_stop_at) > 0 && |
- // fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
- false) { |
- frame_->SpillAll(); |
- __ int3(); |
- } |
+ if (strlen(FLAG_stop_at) > 0 && |
+ // fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
+ false) { |
+ frame_->SpillAll(); |
+ __ int3(); |
+ } |
#endif |
- // New scope to get automatic timing calculation. |
- { // NOLINT |
- HistogramTimerScope codegen_timer(&Counters::code_generation); |
- CodeGenState state(this); |
+ // New scope to get automatic timing calculation. |
+ { // NOLINT |
+ HistogramTimerScope codegen_timer(&Counters::code_generation); |
+ CodeGenState state(this); |
- // Entry: |
- // Stack: receiver, arguments, return address. |
- // ebp: caller's frame pointer |
- // esp: stack pointer |
- // edi: called JS function |
- // esi: callee's context |
- allocator_->Initialize(); |
- frame_->Enter(); |
+ // Entry: |
+ // Stack: receiver, arguments, return address. |
+ // ebp: caller's frame pointer |
+ // esp: stack pointer |
+ // edi: called JS function |
+ // esi: callee's context |
+ allocator_->Initialize(); |
+ frame_->Enter(); |
- __ movq(rax, Immediate(0x2a)); |
- __ Ret(); |
- } |
+ Result return_register = allocator_->Allocate(rax); |
+ |
+ __ movq(return_register.reg(), Immediate(0x54)); // Smi 42 |
+ |
+ GenerateReturnSequence(&return_register); |
} |
} |
+void CodeGenerator::GenerateReturnSequence(Result* return_value) { |
+ // The return value is a live (but not currently reference counted) |
+ // reference to rax. This is safe because the current frame does not |
+ // contain a reference to rax (it is prepared for the return by spilling |
+ // all registers). |
+ if (FLAG_trace) { |
+ frame_->Push(return_value); |
+ // *return_value = frame_->CallRuntime(Runtime::kTraceExit, 1); |
+ } |
+ return_value->ToRegister(rax); |
+ |
+ // Add a label for checking the size of the code used for returning. |
+ Label check_exit_codesize; |
+ masm_->bind(&check_exit_codesize); |
+ |
+ // Leave the frame and return popping the arguments and the |
+ // receiver. |
+ frame_->Exit(); |
+ masm_->ret((scope_->num_parameters() + 1) * kPointerSize); |
+ DeleteFrame(); |
+ |
+ // Check that the size of the code used for returning matches what is |
+ // expected by the debugger. |
+ // ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, |
+ // masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
+} |
+ |
+ |
void CodeGenerator::GenerateFastCaseSwitchJumpTable(SwitchStatement* a, |
int b, |
int c, |