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 }