jitcraft/BytecodeCompiler.cpp
changeset 68 b40b0e18a918
parent 66 cbba1997dc71
child 69 dfce0539a77d
     1.1 --- a/jitcraft/BytecodeCompiler.cpp	Mon Jul 09 22:25:52 2012 -0700
     1.2 +++ b/jitcraft/BytecodeCompiler.cpp	Tue Jul 10 02:11:13 2012 -0700
     1.3 @@ -595,17 +595,29 @@
     1.4  {
     1.5      Local<Type> funType(zone_, node->callee()->type());
     1.6  
     1.7 -    for (size_t i = 0; i < node->arguments()->length(); i++) {
     1.8 +    for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
     1.9          Expression *arg = node->arguments()->at(i);
    1.10  
    1.11 +        // We need to compute a reference if the parameter was in the form:
    1.12 +        //  f(&a)
    1.13 +        // Note this form does not allow: f({})
    1.14 +        // 
    1.15 +        // We also need to compute references for all variadic native
    1.16 +        // arguments, but arrays and references are already in the
    1.17 +        // appropriate form.
    1.18          Local<Type> given(zone_, arg->type());
    1.19 -        Local<Type> actual(zone_, Type::cast(funType->parameters()->at(i)));
    1.20 -        if (actual->isReference()) {
    1.21 -            if (given->isReference()) {
    1.22 -                // The input type is already a reference, so we're just passing
    1.23 -                // it on to the callee.
    1.24 -                arg->accept(this);
    1.25 -            } else if (arg->isNameProxy()) {
    1.26 +        if (i >= funType->parameters()->length())
    1.27 +            assert(funType->isNative() && funType->isNativeVariadic());
    1.28 +        else
    1.29 +            assert(!given->isReference() || !funType->parameterAt(i)->isArray());
    1.30 +
    1.31 +        // If a native is passed to a native, it must only be one level deep.
    1.32 +        assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
    1.33 +
    1.34 +        bool mustPushReference = !given->isArray() && !given->isReference();
    1.35 +
    1.36 +        if (mustPushReference) {
    1.37 +            if (arg->isNameProxy()) {
    1.38                  // :TODO: test with functions and globals
    1.39                  // Compute a reference to the name.
    1.40                  Variable *var = arg->toNameProxy()->binding()->toVariable();
    1.41 @@ -628,7 +640,12 @@
    1.42          }
    1.43      }
    1.44  
    1.45 -    __ callglobal(node->callee()->toNameProxy()->binding()->toNamedFunction()->slot());
    1.46 +    NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
    1.47 +
    1.48 +    if (fun->isNative())
    1.49 +        __ callnative(fun->slot(), node->arguments()->length());
    1.50 +    else
    1.51 +        __ callglobal(fun->slot());
    1.52      __ drop(node->arguments()->length());
    1.53  }
    1.54  
    1.55 @@ -654,6 +671,19 @@
    1.56  void
    1.57  BytecodeCompiler::visit(FunctionStatement *node)
    1.58  {
    1.59 +    if (node->fun()->isNative()) {
    1.60 +        assert(!moduleData_->natives->at(node->fun()->slot()));
    1.61 +
    1.62 +        Local<Type> type(zone_, node->fun()->type());
    1.63 +        Local<String> name(zone_, node->fun()->name());
    1.64 +        Local<Native> native(zone_, Native::New(zone_, type, name));
    1.65 +        if (!native)
    1.66 +            return;
    1.67 +
    1.68 +        moduleData_->natives->set(zone_, node->fun()->slot(), native);
    1.69 +        return;
    1.70 +    }
    1.71 +
    1.72      // If the function has no body, then it's just a declaration.
    1.73      if (!node->body()) {
    1.74          assert(node->fun()->isForward() || node->fun()->isPublic());
    1.75 @@ -779,6 +809,10 @@
    1.76  
    1.77      if (!moduleData_)
    1.78          return NULL;
    1.79 +    
    1.80 +    moduleData_->natives = FixedArray::New(zone_, tree_->scope()->numNatives(), Heap::Tenure_Old);
    1.81 +    if (!moduleData_->natives)
    1.82 +        return NULL;
    1.83  
    1.84      for (size_t i = 0; i < tree_->statements()->length(); i++) {
    1.85          Statement *statement = tree_->statements()->at(i);
    1.86 @@ -788,6 +822,8 @@
    1.87  #ifndef NDEBUG
    1.88      for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
    1.89          assert(moduleData_->module->getFunction(i));
    1.90 +    for (size_t i = 0; i < tree_->scope()->numNatives(); i++)
    1.91 +        assert(moduleData_->natives->at(i));
    1.92  #endif
    1.93  
    1.94      if (moduleData_->publics.length()) {
    1.95 @@ -803,5 +839,7 @@
    1.96          moduleData_->module->setPublics(list);
    1.97      }
    1.98  
    1.99 +    moduleData_->module->setNatives(moduleData_->natives);
   1.100 +
   1.101      return moduleData_->module;
   1.102  }