| Index: src/x64/codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/codegen-x64.cc (revision 2241)
|
| +++ src/x64/codegen-x64.cc (working copy)
|
| @@ -165,8 +165,10 @@
|
| " test_nesting_calls(test_local_variables(1,3), 42, 47),"
|
| " test_local_variables(-25.3, 2));"
|
| " // return test_recursion_with_base(0, 0, 0, 47);\n"
|
| - " var o = { x: 42 };"
|
| + " var x_value = 42;"
|
| + " var o = { x: x_value };"
|
| " var a = [ 1, 2, 3 ];"
|
| + " var x = true ? 42 : 32;"
|
| " return test_if_then_else(0, 46, 47);"
|
| "})()")),
|
| Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")),
|
| @@ -472,8 +474,11 @@
|
| }
|
|
|
|
|
| -void CodeGenerator::VisitEmptyStatement(EmptyStatement* a) {
|
| - UNIMPLEMENTED();
|
| +void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
|
| + ASSERT(!in_spilled_code());
|
| + Comment cmnt(masm_, "// EmptyStatement");
|
| + CodeForStatementPosition(node);
|
| + // nothing to do
|
| }
|
|
|
|
|
| @@ -676,10 +681,38 @@
|
| }
|
|
|
|
|
| -void CodeGenerator::VisitConditional(Conditional* a) {
|
| - UNIMPLEMENTED();
|
| +void CodeGenerator::VisitConditional(Conditional* node) {
|
| + Comment cmnt(masm_, "[ Conditional");
|
| + JumpTarget then;
|
| + JumpTarget else_;
|
| + JumpTarget exit;
|
| + ControlDestination dest(&then, &else_, true);
|
| + LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
|
| +
|
| + if (dest.false_was_fall_through()) {
|
| + // The else target was bound, so we compile the else part first.
|
| + Load(node->else_expression(), typeof_state());
|
| +
|
| + if (then.is_linked()) {
|
| + exit.Jump();
|
| + then.Bind();
|
| + Load(node->then_expression(), typeof_state());
|
| + }
|
| + } else {
|
| + // The then target was bound, so we compile the then part first.
|
| + Load(node->then_expression(), typeof_state());
|
| +
|
| + if (else_.is_linked()) {
|
| + exit.Jump();
|
| + else_.Bind();
|
| + Load(node->else_expression(), typeof_state());
|
| + }
|
| + }
|
| +
|
| + exit.Bind();
|
| }
|
|
|
| +
|
| void CodeGenerator::VisitSlot(Slot* node) {
|
| Comment cmnt(masm_, "[ Slot");
|
| LoadFromSlot(node, typeof_state());
|
| @@ -706,11 +739,79 @@
|
| }
|
|
|
|
|
| -void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* a) {
|
| - UNIMPLEMENTED();
|
| +// Materialize the regexp literal 'node' in the literals array
|
| +// 'literals' of the function. Leave the regexp boilerplate in
|
| +// 'boilerplate'.
|
| +class DeferredRegExpLiteral: public DeferredCode {
|
| + public:
|
| + DeferredRegExpLiteral(Register boilerplate,
|
| + Register literals,
|
| + RegExpLiteral* node)
|
| + : boilerplate_(boilerplate), literals_(literals), node_(node) {
|
| + set_comment("[ DeferredRegExpLiteral");
|
| + }
|
| +
|
| + void Generate();
|
| +
|
| + private:
|
| + Register boilerplate_;
|
| + Register literals_;
|
| + RegExpLiteral* node_;
|
| +};
|
| +
|
| +
|
| +void DeferredRegExpLiteral::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())));
|
| + // RegExp pattern (2).
|
| + __ Push(node_->pattern());
|
| + // RegExp flags (3).
|
| + __ Push(node_->flags());
|
| + __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
|
| + if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax);
|
| }
|
|
|
|
|
| +void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
|
| + Comment cmnt(masm_, "[ RegExp Literal");
|
| +
|
| + // 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 RegExp object. If so,
|
| + // jump to the deferred code passing the literals array.
|
| + DeferredRegExpLiteral* deferred =
|
| + new DeferredRegExpLiteral(boilerplate.reg(), literals.reg(), node);
|
| + __ Cmp(boilerplate.reg(), Factory::undefined_value());
|
| + deferred->Branch(equal);
|
| + deferred->BindExit();
|
| + literals.Unuse();
|
| +
|
| + // Push the boilerplate object.
|
| + frame_->Push(&boilerplate);
|
| +}
|
| +
|
| +
|
| // Materialize the object literal 'node' in the literals array
|
| // 'literals' of the function. Leave the object boilerplate in
|
| // 'boilerplate'.
|
| @@ -797,8 +898,18 @@
|
| if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
|
| // else fall through.
|
| case ObjectLiteral::Property::COMPUTED: {
|
| - // TODO(X64): Implement setting of computed values in object literals.
|
| - UNIMPLEMENTED();
|
| + Handle<Object> key(property->key()->handle());
|
| + if (key->IsSymbol()) {
|
| + // Duplicate the object as the IC receiver.
|
| + frame_->Dup();
|
| + Load(property->value());
|
| + frame_->Push(key);
|
| + Result ignored = frame_->CallStoreIC();
|
| + // Drop the duplicated receiver and ignore the result.
|
| + frame_->Drop();
|
| + break;
|
| + }
|
| + // Fall through
|
| }
|
| case ObjectLiteral::Property::PROTOTYPE: {
|
| // Duplicate the object as an argument to the runtime call.
|
| @@ -1889,6 +2000,10 @@
|
| } else if (slot->type() == Slot::LOCAL) {
|
| frame_->StoreToLocalAt(slot->index());
|
| } else {
|
| + // The other slot types (LOOKUP and GLOBAL) cannot reach here.
|
| + //
|
| + // The use of SlotOperand below is safe for an unspilled frame
|
| + // because the slot is a context slot.
|
| ASSERT(slot->type() == Slot::CONTEXT);
|
| frame_->Dup();
|
| Result value = frame_->Pop();
|
|
|