| Index: src/x64/codegen-x64.cc
 | 
| ===================================================================
 | 
| --- src/x64/codegen-x64.cc	(revision 2216)
 | 
| +++ src/x64/codegen-x64.cc	(working copy)
 | 
| @@ -103,7 +103,15 @@
 | 
|  void CodeGenerator::TestCodeGenerator() {
 | 
|    // Compile a function from a string, and run it.
 | 
|    Handle<JSFunction> test_function = Compiler::Compile(
 | 
| -      Factory::NewStringFromAscii(CStrVector("39; 42;")),
 | 
| +      Factory::NewStringFromAscii(CStrVector(
 | 
| +          "39;"
 | 
| +          "(function(){return 43})();"
 | 
| +          "42;"
 | 
| +          // "function foo(x, y){return x;};"
 | 
| +          "43;"
 | 
| +          // "foo(2,3);"
 | 
| +          "44;"
 | 
| +          "(function(){return (function(){return 47})()})();")),
 | 
|        Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")),
 | 
|        0,
 | 
|        0,
 | 
| @@ -132,7 +140,7 @@
 | 
|                        &pending_exceptions);
 | 
|    // Function compiles and runs, but returns a JSFunction object.
 | 
|    CHECK(result->IsSmi());
 | 
| -  CHECK_EQ(42, Smi::cast(*result)->value());
 | 
| +  CHECK_EQ(47, Smi::cast(*result)->value());
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -370,15 +378,44 @@
 | 
|    UNIMPLEMENTED();
 | 
|  }
 | 
|  
 | 
| -void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* a) {
 | 
| -  UNIMPLEMENTED();
 | 
| +
 | 
| +void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
 | 
| +  // Call the runtime to instantiate the function boilerplate object.
 | 
| +  // The inevitable call will sync frame elements to memory anyway, so
 | 
| +  // we do it eagerly to allow us to push the arguments directly into
 | 
| +  // place.
 | 
| +  ASSERT(boilerplate->IsBoilerplate());
 | 
| +  frame_->SyncRange(0, frame_->element_count() - 1);
 | 
| +
 | 
| +  // Push the boilerplate on the stack.
 | 
| +  __ movq(kScratchRegister, boilerplate, RelocInfo::EMBEDDED_OBJECT);
 | 
| +  frame_->EmitPush(kScratchRegister);
 | 
| +
 | 
| +  // Create a new closure.
 | 
| +  frame_->EmitPush(rsi);
 | 
| +  Result result = frame_->CallRuntime(Runtime::kNewClosure, 2);
 | 
| +  frame_->Push(&result);
 | 
|  }
 | 
|  
 | 
| +
 | 
| +void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
 | 
| +  Comment cmnt(masm_, "[ FunctionLiteral");
 | 
| +
 | 
| +  // Build the function boilerplate and instantiate it.
 | 
| +  Handle<JSFunction> boilerplate = BuildBoilerplate(node);
 | 
| +  // Check for stack-overflow exception.
 | 
| +  if (HasStackOverflow()) return;
 | 
| +  InstantiateBoilerplate(boilerplate);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void CodeGenerator::VisitFunctionBoilerplateLiteral(
 | 
| -    FunctionBoilerplateLiteral* a) {
 | 
| -  UNIMPLEMENTED();
 | 
| +    FunctionBoilerplateLiteral* node) {
 | 
| +  Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
 | 
| +  InstantiateBoilerplate(node->boilerplate());
 | 
|  }
 | 
|  
 | 
| +
 | 
|  void CodeGenerator::VisitConditional(Conditional* a) {
 | 
|    UNIMPLEMENTED();
 | 
|  }
 | 
| @@ -521,10 +558,153 @@
 | 
|    UNIMPLEMENTED();
 | 
|  }
 | 
|  
 | 
| -void CodeGenerator::VisitCall(Call* a) {
 | 
| -  UNIMPLEMENTED();
 | 
| +
 | 
| +void CodeGenerator::VisitCall(Call* node) {
 | 
| +  Comment cmnt(masm_, "[ Call");
 | 
| +
 | 
| +  ZoneList<Expression*>* args = node->arguments();
 | 
| +
 | 
| +  CodeForStatementPosition(node);
 | 
| +
 | 
| +  // Check if the function is a variable or a property.
 | 
| +  Expression* function = node->expression();
 | 
| +  Variable* var = function->AsVariableProxy()->AsVariable();
 | 
| +  Property* property = function->AsProperty();
 | 
| +
 | 
| +  // ------------------------------------------------------------------------
 | 
| +  // Fast-case: Use inline caching.
 | 
| +  // ---
 | 
| +  // According to ECMA-262, section 11.2.3, page 44, the function to call
 | 
| +  // must be resolved after the arguments have been evaluated. The IC code
 | 
| +  // automatically handles this by loading the arguments before the function
 | 
| +  // is resolved in cache misses (this also holds for megamorphic calls).
 | 
| +  // ------------------------------------------------------------------------
 | 
| +
 | 
| +  if (var != NULL && !var->is_this() && var->is_global()) {
 | 
| +    // ----------------------------------
 | 
| +    // JavaScript example: 'foo(1, 2, 3)'  // foo is global
 | 
| +    // ----------------------------------
 | 
| +
 | 
| +    // Push the name of the function and the receiver onto the stack.
 | 
| +    frame_->Push(var->name());
 | 
| +
 | 
| +    // Pass the global object as the receiver and let the IC stub
 | 
| +    // patch the stack to use the global proxy as 'this' in the
 | 
| +    // invoked function.
 | 
| +    LoadGlobal();
 | 
| +
 | 
| +    // Load the arguments.
 | 
| +    int arg_count = args->length();
 | 
| +    for (int i = 0; i < arg_count; i++) {
 | 
| +      Load(args->at(i));
 | 
| +    }
 | 
| +
 | 
| +    // Call the IC initialization code.
 | 
| +    CodeForSourcePosition(node->position());
 | 
| +    Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT,
 | 
| +                                       arg_count,
 | 
| +                                       loop_nesting());
 | 
| +    frame_->RestoreContextRegister();
 | 
| +    // Replace the function on the stack with the result.
 | 
| +    frame_->SetElementAt(0, &result);
 | 
| +  } else if (var != NULL && var->slot() != NULL &&
 | 
| +             var->slot()->type() == Slot::LOOKUP) {
 | 
| +    // TODO(X64): Enable calls of non-global functions.
 | 
| +    UNIMPLEMENTED();
 | 
| +    /*
 | 
| +    // ----------------------------------
 | 
| +    // JavaScript example: 'with (obj) foo(1, 2, 3)'  // foo is in obj
 | 
| +    // ----------------------------------
 | 
| +
 | 
| +    // Load the function from the context.  Sync the frame so we can
 | 
| +    // push the arguments directly into place.
 | 
| +    frame_->SyncRange(0, frame_->element_count() - 1);
 | 
| +    frame_->EmitPush(esi);
 | 
| +    frame_->EmitPush(Immediate(var->name()));
 | 
| +    frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
 | 
| +    // The runtime call returns a pair of values in eax and edx.  The
 | 
| +    // looked-up function is in eax and the receiver is in edx.  These
 | 
| +    // register references are not ref counted here.  We spill them
 | 
| +    // eagerly since they are arguments to an inevitable call (and are
 | 
| +    // not sharable by the arguments).
 | 
| +    ASSERT(!allocator()->is_used(eax));
 | 
| +    frame_->EmitPush(eax);
 | 
| +
 | 
| +    // Load the receiver.
 | 
| +    ASSERT(!allocator()->is_used(edx));
 | 
| +    frame_->EmitPush(edx);
 | 
| +
 | 
| +    // Call the function.
 | 
| +    CallWithArguments(args, node->position());
 | 
| +    */
 | 
| +  } else if (property != NULL) {
 | 
| +    UNIMPLEMENTED();
 | 
| +    /*
 | 
| +    // Check if the key is a literal string.
 | 
| +    Literal* literal = property->key()->AsLiteral();
 | 
| +
 | 
| +    if (literal != NULL && literal->handle()->IsSymbol()) {
 | 
| +      // ------------------------------------------------------------------
 | 
| +      // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
 | 
| +      // ------------------------------------------------------------------
 | 
| +
 | 
| +      // Push the name of the function and the receiver onto the stack.
 | 
| +      frame_->Push(literal->handle());
 | 
| +      Load(property->obj());
 | 
| +
 | 
| +      // Load the arguments.
 | 
| +      int arg_count = args->length();
 | 
| +      for (int i = 0; i < arg_count; i++) {
 | 
| +        Load(args->at(i));
 | 
| +      }
 | 
| +
 | 
| +      // Call the IC initialization code.
 | 
| +      CodeForSourcePosition(node->position());
 | 
| +      Result result =
 | 
| +          frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, loop_nesting());
 | 
| +      frame_->RestoreContextRegister();
 | 
| +      // Replace the function on the stack with the result.
 | 
| +      frame_->SetElementAt(0, &result);
 | 
| +
 | 
| +    } else {
 | 
| +      // -------------------------------------------
 | 
| +      // JavaScript example: 'array[index](1, 2, 3)'
 | 
| +      // -------------------------------------------
 | 
| +
 | 
| +      // Load the function to call from the property through a reference.
 | 
| +      Reference ref(this, property);
 | 
| +      ref.GetValue(NOT_INSIDE_TYPEOF);
 | 
| +
 | 
| +      // Pass receiver to called function.
 | 
| +      if (property->is_synthetic()) {
 | 
| +        // Use global object as receiver.
 | 
| +        LoadGlobalReceiver();
 | 
| +      } else {
 | 
| +        // The reference's size is non-negative.
 | 
| +        frame_->PushElementAt(ref.size());
 | 
| +      }
 | 
| +
 | 
| +      // Call the function.
 | 
| +      CallWithArguments(args, node->position());
 | 
| +    }
 | 
| +    */
 | 
| +  } else {
 | 
| +    // ----------------------------------
 | 
| +    // JavaScript example: 'foo(1, 2, 3)'  // foo is not global
 | 
| +    // ----------------------------------
 | 
| +
 | 
| +    // Load the function.
 | 
| +    Load(function);
 | 
| +
 | 
| +    // Pass the global proxy as the receiver.
 | 
| +    LoadGlobalReceiver();
 | 
| +
 | 
| +    // Call the function.
 | 
| +    CallWithArguments(args, node->position());
 | 
| +  }
 | 
|  }
 | 
|  
 | 
| +
 | 
|  void CodeGenerator::VisitCallEval(CallEval* a) {
 | 
|    UNIMPLEMENTED();
 | 
|  }
 | 
| @@ -537,6 +717,7 @@
 | 
|    UNIMPLEMENTED();
 | 
|  }
 | 
|  
 | 
| +
 | 
|  void CodeGenerator::VisitUnaryOperation(UnaryOperation* a) {
 | 
|    UNIMPLEMENTED();
 | 
|  }
 | 
| @@ -1216,6 +1397,16 @@
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +
 | 
| +void CodeGenerator::LoadGlobalReceiver() {
 | 
| +  Result temp = allocator_->Allocate();
 | 
| +  Register reg = temp.reg();
 | 
| +  __ movq(reg, GlobalObject());
 | 
| +  __ movq(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset));
 | 
| +  frame_->Push(&temp);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  #undef __
 | 
|  
 | 
|  // End of CodeGenerator implementation.
 | 
| @@ -1588,14 +1779,61 @@
 | 
|  
 | 
|  
 | 
|  void CallFunctionStub::Generate(MacroAssembler* masm) {
 | 
| +  Label slow;
 | 
| +
 | 
| +  // Get the function to call from the stack.
 | 
| +  // +2 ~ receiver, return address
 | 
| +  __ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize));
 | 
| +
 | 
| +  // Check that the function really is a JavaScript function.
 | 
| +  __ testq(rdi, Immediate(kSmiTagMask));
 | 
| +  __ j(zero, &slow);
 | 
| +  // Goto slow case if we do not have a function.
 | 
| +  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
 | 
| +  __ j(not_equal, &slow);
 | 
| +
 | 
| +  // Fast-case: Just invoke the function.
 | 
| +  ParameterCount actual(argc_);
 | 
| +  __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
 | 
| +
 | 
| +  // Slow-case: Non-function called.
 | 
| +  __ bind(&slow);
 | 
| +  __ Set(rax, argc_);
 | 
| +  __ Set(rbx, 0);
 | 
| +  __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
 | 
| +  Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
 | 
| +  __ Jump(adaptor, RelocInfo::CODE_TARGET);
 | 
|  }
 | 
|  
 | 
|  
 | 
| +// Call the function just below TOS on the stack with the given
 | 
| +// arguments. The receiver is the TOS.
 | 
| +void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
 | 
| +                                      int position) {
 | 
| +  // Push the arguments ("left-to-right") on the stack.
 | 
| +  int arg_count = args->length();
 | 
| +  for (int i = 0; i < arg_count; i++) {
 | 
| +    Load(args->at(i));
 | 
| +  }
 | 
| +
 | 
| +  // Record the position for debugging purposes.
 | 
| +  CodeForSourcePosition(position);
 | 
| +
 | 
| +  // Use the shared code stub to call the function.
 | 
| +  InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
 | 
| +  CallFunctionStub call_function(arg_count, in_loop);
 | 
| +  Result answer = frame_->CallStub(&call_function, arg_count + 1);
 | 
| +  // Restore context and replace function on the stack with the
 | 
| +  // result of the stub invocation.
 | 
| +  frame_->RestoreContextRegister();
 | 
| +  frame_->SetElementAt(0, &answer);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void InstanceofStub::Generate(MacroAssembler* masm) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -
 | 
|  void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
 | 
|    // The displacement is used for skipping the return address and the
 | 
|    // frame pointer on the stack. It is the offset of the last
 | 
| 
 |