Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2485)

Unified Diff: src/x64/codegen-x64.cc

Issue 140060: Enable code generation for array literals.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/codegen-x64.cc
===================================================================
--- src/x64/codegen-x64.cc (revision 2232)
+++ src/x64/codegen-x64.cc (working copy)
@@ -155,6 +155,7 @@
" test_nesting_calls(test_local_variables(1,3), 42, 47),"
" test_local_variables(-25.3, 2));"
" var o = { x: 42 };"
+ " var a = [ 1, 2, 3 ];"
" return test_if_then_else(1, 47, 39);"
"})()")),
Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")),
@@ -310,7 +311,7 @@
// all registers).
if (FLAG_trace) {
frame_->Push(return_value);
- // *return_value = frame_->CallRuntime(Runtime::kTraceExit, 1);
+ *return_value = frame_->CallRuntime(Runtime::kTraceExit, 1);
}
return_value->ToRegister(rax);
@@ -324,6 +325,8 @@
masm_->ret((scope_->num_parameters() + 1) * kPointerSize);
DeleteFrame();
+ // TODO(x64): introduce kX64JSReturnSequenceLength and enable assert.
+
// Check that the size of the code used for returning matches what is
// expected by the debugger.
// ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
@@ -576,7 +579,7 @@
CodeForStatementPosition(node);
Load(node->expression());
Result return_value = frame_->Pop();
- /* if (function_return_is_shadowed_) {
+ if (function_return_is_shadowed_) {
function_return_.Jump(&return_value);
} else {
frame_->PrepareForReturn();
@@ -589,8 +592,6 @@
GenerateReturnSequence(&return_value);
}
}
- */
- GenerateReturnSequence(&return_value);
}
@@ -683,7 +684,7 @@
} else {
ASSERT(var->is_global());
Reference ref(this, node);
- // ref.GetValue(typeof_state());
+ ref.GetValue(typeof_state());
}
}
@@ -728,10 +729,7 @@
// Literal index (1).
__ push(Immediate(Smi::FromInt(node_->literal_index())));
// Constant properties (2).
- __ movq(kScratchRegister,
- node_->constant_properties(),
- RelocInfo::EMBEDDED_OBJECT);
- __ push(kScratchRegister);
+ __ PushHeapObject(node_->constant_properties());
__ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax);
}
@@ -763,10 +761,7 @@
// 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);
+ __ CmpHeapObject(boilerplate.reg(), Factory::undefined_value());
deferred->Branch(equal);
deferred->BindExit();
literals.Unuse();
@@ -828,10 +823,125 @@
}
}
-void CodeGenerator::VisitArrayLiteral(ArrayLiteral* a) {
- UNIMPLEMENTED();
+
+// Materialize the array literal 'node' in the literals array 'literals'
+// of the function. Leave the array boilerplate in 'boilerplate'.
+class DeferredArrayLiteral: public DeferredCode {
+ public:
+ DeferredArrayLiteral(Register boilerplate,
+ Register literals,
+ ArrayLiteral* node)
+ : boilerplate_(boilerplate), literals_(literals), node_(node) {
+ set_comment("[ DeferredArrayLiteral");
+ }
+
+ void Generate();
+
+ private:
+ Register boilerplate_;
+ Register literals_;
+ ArrayLiteral* node_;
+};
+
+
+void DeferredArrayLiteral::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).
+ __ PushHeapObject(node_->literals());
+ __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
+ if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax);
}
+
+void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
+ Comment cmnt(masm_, "[ ArrayLiteral");
+
+ // 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.
+ DeferredArrayLiteral* deferred =
+ new DeferredArrayLiteral(boilerplate.reg(), literals.reg(), node);
+ __ CmpHeapObject(boilerplate.reg(), Factory::undefined_value());
+ deferred->Branch(equal);
+ deferred->BindExit();
+ literals.Unuse();
+
+ // Push the resulting array literal boilerplate on the stack.
+ 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);
+
+ // Generate code to set the elements in the array that are not
+ // literals.
+ for (int i = 0; i < node->values()->length(); i++) {
+ Expression* value = node->values()->at(i);
+
+ // If value is a literal the property value is already set in the
+ // boilerplate object.
+ if (value->AsLiteral() != NULL) continue;
+ // If value is a materialized literal the property value is already set
+ // in the boilerplate object if it is simple.
+ if (CompileTimeValue::IsCompileTimeValue(value)) continue;
+
+ // The property must be set by generated code.
+ Load(value);
+
+ // Get the property value off the stack.
+ Result prop_value = frame_->Pop();
+ prop_value.ToRegister();
+
+ // Fetch the array literal while leaving a copy on the stack and
+ // use it to get the elements array.
+ frame_->Dup();
+ Result elements = frame_->Pop();
+ elements.ToRegister();
+ frame_->Spill(elements.reg());
+ // Get the elements array.
+ __ movq(elements.reg(),
+ FieldOperand(elements.reg(), JSObject::kElementsOffset));
+
+ // Write to the indexed properties array.
+ int offset = i * kPointerSize + Array::kHeaderSize;
+ __ movq(FieldOperand(elements.reg(), offset), prop_value.reg());
+
+ // Update the write barrier for the array address.
+ frame_->Spill(prop_value.reg()); // Overwritten by the write barrier.
+ Result scratch = allocator_->Allocate();
+ ASSERT(scratch.is_valid());
+ __ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg());
+ }
+}
+
+
void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* a) {
UNIMPLEMENTED();
}
@@ -1290,20 +1400,15 @@
// Fast case checks.
// 'false' => false.
- __ movq(kScratchRegister, Factory::false_value(), RelocInfo::EMBEDDED_OBJECT);
- __ cmpq(value.reg(), kScratchRegister);
+ __ CmpHeapObject(value.reg(), Factory::false_value());
dest->false_target()->Branch(equal);
// 'true' => true.
- __ movq(kScratchRegister, Factory::true_value(), RelocInfo::EMBEDDED_OBJECT);
- __ cmpq(value.reg(), kScratchRegister);
+ __ CmpHeapObject(value.reg(), Factory::true_value());
dest->true_target()->Branch(equal);
// 'undefined' => false.
- __ movq(kScratchRegister,
- Factory::undefined_value(),
- RelocInfo::EMBEDDED_OBJECT);
- __ cmpq(value.reg(), kScratchRegister);
+ __ CmpHeapObject(value.reg(), Factory::undefined_value());
dest->false_target()->Branch(equal);
// Smi => false iff zero.
@@ -1632,9 +1737,7 @@
value,
&slow));
if (potential_slot->var()->mode() == Variable::CONST) {
- __ movq(kScratchRegister, Factory::the_hole_value(),
- RelocInfo::EMBEDDED_OBJECT);
- __ cmpq(value.reg(), kScratchRegister);
+ __ CmpHeapObject(value.reg(), Factory::the_hole_value());
done.Branch(not_equal, &value);
__ movq(value.reg(), Factory::undefined_value(),
RelocInfo::EMBEDDED_OBJECT);
@@ -1675,9 +1778,7 @@
Comment cmnt(masm_, "[ Load const");
JumpTarget exit;
__ movq(rcx, SlotOperand(slot, rcx));
- __ movq(kScratchRegister, Factory::the_hole_value(),
- RelocInfo::EMBEDDED_OBJECT);
- __ cmpq(rcx, kScratchRegister);
+ __ CmpHeapObject(rcx, Factory::the_hole_value());
exit.Branch(not_equal);
__ movq(rcx, Factory::undefined_value(), RelocInfo::EMBEDDED_OBJECT);
exit.Bind();
@@ -1761,9 +1862,7 @@
VirtualFrame::SpilledScope spilled_scope;
Comment cmnt(masm_, "[ Init const");
__ movq(rcx, SlotOperand(slot, rcx));
- __ movq(kScratchRegister, Factory::the_hole_value(),
- RelocInfo::EMBEDDED_OBJECT);
- __ cmpq(rcx, kScratchRegister);
+ __ CmpHeapObject(rcx, Factory::the_hole_value());
exit.Branch(not_equal);
}
@@ -1850,13 +1949,18 @@
// Stub classes have public member named masm, not masm_.
#define __ ACCESS_MASM(masm)
+
+void Reference::GetValue(TypeofState typeof_state) {
+ UNIMPLEMENTED();
+}
+
+
void ToBooleanStub::Generate(MacroAssembler* masm) {
Label false_result, true_result, not_string;
__ movq(rax, Operand(rsp, 1 * kPointerSize));
// 'null' => false.
- __ movq(kScratchRegister, Factory::null_value(), RelocInfo::EMBEDDED_OBJECT);
- __ cmpq(rax, kScratchRegister);
+ __ CmpHeapObject(rax, Factory::null_value());
__ j(equal, &false_result);
// Get the map and type of the heap object.
@@ -1885,10 +1989,7 @@
__ bind(&not_string);
// HeapNumber => false iff +0, -0, or NaN.
- __ movq(kScratchRegister,
- Factory::heap_number_map(),
- RelocInfo::EMBEDDED_OBJECT);
- __ cmpq(rdx, kScratchRegister);
+ __ CmpHeapObject(rdx, Factory::heap_number_map());
__ j(not_equal, &true_result);
// TODO(x64): Don't use fp stack, use MMX registers?
__ fldz(); // Load zero onto fp stack
« no previous file with comments | « no previous file | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698