X64 implementation: Test Compiler::Compile by compiling and running a function.

Review URL: http://codereview.chromium.org/126191

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2178 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2009-06-16 08:25:08 +00:00
parent fb03c8414f
commit 7358e1980c

View File

@ -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::DeclareGlobals(Handle<FixedArray> a) {
}
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_ = &register_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_ = &register_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,