Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 2231) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -39,13 +39,37 @@ |
namespace v8 { |
namespace internal { |
+#define __ ACCESS_MASM(masm_) |
+ |
// ------------------------------------------------------------------------- |
// Platform-specific DeferredCode functions. |
-void DeferredCode::SaveRegisters() { UNIMPLEMENTED(); } |
+void DeferredCode::SaveRegisters() { |
+ for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { |
+ int action = registers_[i]; |
+ if (action == kPush) { |
+ __ push(RegisterAllocator::ToRegister(i)); |
+ } else if (action != kIgnore && (action & kSyncedFlag) == 0) { |
+ __ movq(Operand(rbp, action), RegisterAllocator::ToRegister(i)); |
+ } |
+ } |
+} |
-void DeferredCode::RestoreRegisters() { UNIMPLEMENTED(); } |
+void DeferredCode::RestoreRegisters() { |
+ // Restore registers in reverse order due to the stack. |
+ for (int i = RegisterAllocator::kNumRegisters - 1; i >= 0; i--) { |
+ int action = registers_[i]; |
+ if (action == kPush) { |
+ __ pop(RegisterAllocator::ToRegister(i)); |
+ } else if (action != kIgnore) { |
+ action &= ~kSyncedFlag; |
+ __ movq(RegisterAllocator::ToRegister(i), Operand(rbp, action)); |
+ } |
+ } |
+} |
+#undef __ |
+ |
// ------------------------------------------------------------------------- |
// CodeGenState implementation. |
@@ -112,7 +136,6 @@ |
FLAG_print_builtin_ast = true; |
#endif |
FLAG_use_ic = false; |
- FLAG_lazy = false; |
Handle<JSFunction> test_function = Compiler::Compile( |
Factory::NewStringFromAscii(CStrVector( |
@@ -134,6 +157,8 @@ |
" test_local_variables(" |
" test_nesting_calls(test_local_variables(1,3), 42, 47)," |
" test_local_variables(-25.3, 2));" |
+ " var x_value = 42;" |
+ " var o = { x: x_value };" |
William Hesse
2009/06/22 10:31:35
Why isn't this hitting the unimplemented
case Ob
Mads Ager (chromium)
2009/06/22 10:51:05
It is, accidentally uploaded this instead of just
|
" return test_if_then_else(1, 47, 39);" |
"})()")), |
Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), |
@@ -677,10 +702,136 @@ |
UNIMPLEMENTED(); |
} |
-void CodeGenerator::VisitObjectLiteral(ObjectLiteral* a) { |
- UNIMPLEMENTED(); |
+ |
+// Materialize the object literal 'node' in the literals array |
+// 'literals' of the function. Leave the object boilerplate in |
+// 'boilerplate'. |
+class DeferredObjectLiteral: public DeferredCode { |
+ public: |
+ DeferredObjectLiteral(Register boilerplate, |
+ Register literals, |
+ ObjectLiteral* node) |
+ : boilerplate_(boilerplate), literals_(literals), node_(node) { |
+ set_comment("[ DeferredObjectLiteral"); |
+ } |
+ |
+ void Generate(); |
+ |
+ private: |
+ Register boilerplate_; |
+ Register literals_; |
+ ObjectLiteral* node_; |
+}; |
+ |
+ |
+void DeferredObjectLiteral::Generate() { |
+ // Since the entry is undefined we call the runtime system to |
+ // compute the literal. |
+ // Literal array (0). |
+ __ push(literals_); |
+ // Literal index (1). |
+ __ push(Immediate(Smi::FromInt(node_->literal_index()))); |
+ // Constant properties (2). |
+ __ movq(kScratchRegister, |
+ node_->constant_properties(), |
+ RelocInfo::EMBEDDED_OBJECT); |
+ __ push(kScratchRegister); |
+ __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); |
+ if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax); |
} |
+ |
+void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { |
+ Comment cmnt(masm_, "[ ObjectLiteral"); |
+ |
+ // Retrieve the literals array and check the allocated entry. Begin |
+ // with a writable copy of the function of this activation in a |
+ // register. |
+ frame_->PushFunction(); |
+ Result literals = frame_->Pop(); |
+ literals.ToRegister(); |
+ frame_->Spill(literals.reg()); |
+ |
+ // Load the literals array of the function. |
+ __ movq(literals.reg(), |
+ FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); |
+ |
+ // Load the literal at the ast saved index. |
+ Result boilerplate = allocator_->Allocate(); |
+ ASSERT(boilerplate.is_valid()); |
+ int literal_offset = |
+ FixedArray::kHeaderSize + node->literal_index() * kPointerSize; |
+ __ movq(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset)); |
+ |
+ // Check whether we need to materialize the object literal boilerplate. |
+ // If so, jump to the deferred code passing the literals array. |
+ DeferredObjectLiteral* deferred = |
+ new DeferredObjectLiteral(boilerplate.reg(), literals.reg(), node); |
+ __ movq(kScratchRegister, |
+ Factory::undefined_value(), |
+ RelocInfo::EMBEDDED_OBJECT); |
+ __ cmpq(boilerplate.reg(), kScratchRegister); |
+ deferred->Branch(equal); |
+ deferred->BindExit(); |
+ literals.Unuse(); |
+ |
+ // Push the boilerplate object. |
+ frame_->Push(&boilerplate); |
+ // Clone the boilerplate object. |
+ Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate; |
+ if (node->depth() == 1) { |
+ clone_function_id = Runtime::kCloneShallowLiteralBoilerplate; |
+ } |
+ Result clone = frame_->CallRuntime(clone_function_id, 1); |
+ // Push the newly cloned literal object as the result. |
+ frame_->Push(&clone); |
+ |
+ for (int i = 0; i < node->properties()->length(); i++) { |
+ ObjectLiteral::Property* property = node->properties()->at(i); |
+ switch (property->kind()) { |
+ case ObjectLiteral::Property::CONSTANT: |
+ break; |
+ case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
+ if (CompileTimeValue::IsCompileTimeValue(property->value())) break; |
+ // else fall through. |
+ case ObjectLiteral::Property::COMPUTED: { |
+ // TODO(X64): Implement setting of computed values in object literals. |
+ UNIMPLEMENTED(); |
+ } |
+ case ObjectLiteral::Property::PROTOTYPE: { |
+ // Duplicate the object as an argument to the runtime call. |
+ frame_->Dup(); |
+ Load(property->key()); |
+ Load(property->value()); |
+ Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); |
+ // Ignore the result. |
+ break; |
+ } |
+ case ObjectLiteral::Property::SETTER: { |
+ // Duplicate the object as an argument to the runtime call. |
+ frame_->Dup(); |
+ Load(property->key()); |
+ frame_->Push(Smi::FromInt(1)); |
+ Load(property->value()); |
+ Result ignored = frame_->CallRuntime(Runtime::kDefineAccessor, 4); |
+ // Ignore the result. |
+ break; |
+ } |
+ case ObjectLiteral::Property::GETTER: { |
+ // Duplicate the object as an argument to the runtime call. |
+ frame_->Dup(); |
+ Load(property->key()); |
+ frame_->Push(Smi::FromInt(0)); |
+ Load(property->value()); |
+ Result ignored = frame_->CallRuntime(Runtime::kDefineAccessor, 4); |
+ // Ignore the result. |
+ break; |
+ } |
+ default: UNREACHABLE(); |
+ } |
+ } |
+} |
+ |
void CodeGenerator::VisitArrayLiteral(ArrayLiteral* a) { |
UNIMPLEMENTED(); |
} |