| Index: src/wasm/asm-wasm-builder.cc | 
| diff --git a/src/wasm/asm-wasm-builder.cc b/src/wasm/asm-wasm-builder.cc | 
| index fae07e98e56d969b9712515a0934135b7fedf76e..1d5e674e1c8b59e8c23e0ab8dcbccc847da92c51 100644 | 
| --- a/src/wasm/asm-wasm-builder.cc | 
| +++ b/src/wasm/asm-wasm-builder.cc | 
| @@ -51,7 +51,8 @@ class AsmWasmBuilderImpl : public AstVisitor { | 
| next_table_index_(0), | 
| function_tables_(HashMap::PointersMatch, | 
| ZoneHashMap::kDefaultHashMapCapacity, | 
| -                         ZoneAllocationPolicy(zone)) { | 
| +                         ZoneAllocationPolicy(zone)), | 
| +        imported_function_table_(this) { | 
| InitializeAstVisitor(isolate); | 
| } | 
|  | 
| @@ -367,35 +368,27 @@ class AsmWasmBuilderImpl : public AstVisitor { | 
| void VisitVariableProxy(VariableProxy* expr) { | 
| if (in_function_) { | 
| Variable* var = expr->var(); | 
| -      if (var->is_function()) { | 
| -        DCHECK(!is_set_op_); | 
| -        std::vector<uint8_t> index = | 
| -            UnsignedLEB128From(LookupOrInsertFunction(var)); | 
| -        current_function_builder_->EmitCode( | 
| -            &index[0], static_cast<uint32_t>(index.size())); | 
| -      } else { | 
| -        if (is_set_op_) { | 
| -          if (var->IsContextSlot()) { | 
| -            current_function_builder_->Emit(kExprStoreGlobal); | 
| -          } else { | 
| -            current_function_builder_->Emit(kExprSetLocal); | 
| -          } | 
| -          is_set_op_ = false; | 
| +      if (is_set_op_) { | 
| +        if (var->IsContextSlot()) { | 
| +          current_function_builder_->Emit(kExprStoreGlobal); | 
| } else { | 
| -          if (var->IsContextSlot()) { | 
| -            current_function_builder_->Emit(kExprLoadGlobal); | 
| -          } else { | 
| -            current_function_builder_->Emit(kExprGetLocal); | 
| -          } | 
| +          current_function_builder_->Emit(kExprSetLocal); | 
| } | 
| -        LocalType var_type = TypeOf(expr); | 
| -        DCHECK(var_type != kAstStmt); | 
| +        is_set_op_ = false; | 
| +      } else { | 
| if (var->IsContextSlot()) { | 
| -          AddLeb128(LookupOrInsertGlobal(var, var_type), false); | 
| +          current_function_builder_->Emit(kExprLoadGlobal); | 
| } else { | 
| -          AddLeb128(LookupOrInsertLocal(var, var_type), true); | 
| +          current_function_builder_->Emit(kExprGetLocal); | 
| } | 
| } | 
| +      LocalType var_type = TypeOf(expr); | 
| +      DCHECK(var_type != kAstStmt); | 
| +      if (var->IsContextSlot()) { | 
| +        AddLeb128(LookupOrInsertGlobal(var, var_type), false); | 
| +      } else { | 
| +        AddLeb128(LookupOrInsertLocal(var, var_type), true); | 
| +      } | 
| } | 
| } | 
|  | 
| @@ -508,11 +501,80 @@ class AsmWasmBuilderImpl : public AstVisitor { | 
| return reinterpret_cast<FunctionTableIndices*>(entry->value); | 
| } | 
|  | 
| +  class ImportedFunctionTable { | 
| +   private: | 
| +    class ImportedFunctionIndices : public ZoneObject { | 
| +     public: | 
| +      const unsigned char* name_; | 
| +      int name_length_; | 
| +      WasmModuleBuilder::SignatureMap signature_to_index_; | 
| + | 
| +      ImportedFunctionIndices(const unsigned char* name, int name_length, | 
| +                              Zone* zone) | 
| +          : name_(name), name_length_(name_length), signature_to_index_(zone) {} | 
| +    }; | 
| +    ZoneHashMap table_; | 
| +    AsmWasmBuilderImpl* builder_; | 
| + | 
| +   public: | 
| +    explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) | 
| +        : table_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, | 
| +                 ZoneAllocationPolicy(builder->zone())), | 
| +          builder_(builder) {} | 
| + | 
| +    void AddImport(Variable* v, const unsigned char* name, int name_length) { | 
| +      ImportedFunctionIndices* indices = new (builder_->zone()) | 
| +          ImportedFunctionIndices(name, name_length, builder_->zone()); | 
| +      ZoneHashMap::Entry* entry = table_.LookupOrInsert( | 
| +          v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); | 
| +      entry->value = indices; | 
| +    } | 
| + | 
| +    uint16_t GetFunctionIndex(Variable* v, FunctionSig* sig) { | 
| +      ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v)); | 
| +      DCHECK(entry != nullptr); | 
| +      ImportedFunctionIndices* indices = | 
| +          reinterpret_cast<ImportedFunctionIndices*>(entry->value); | 
| +      WasmModuleBuilder::SignatureMap::iterator pos = | 
| +          indices->signature_to_index_.find(sig); | 
| +      if (pos != indices->signature_to_index_.end()) { | 
| +        return pos->second; | 
| +      } else { | 
| +        uint16_t index = builder_->builder_->AddFunction(); | 
| +        indices->signature_to_index_[sig] = index; | 
| +        WasmFunctionBuilder* function = builder_->builder_->FunctionAt(index); | 
| +        function->External(1); | 
| +        function->SetName(indices->name_, indices->name_length_); | 
| +        if (sig->return_count() > 0) { | 
| +          function->ReturnType(sig->GetReturn()); | 
| +        } | 
| +        for (size_t i = 0; i < sig->parameter_count(); i++) { | 
| +          function->AddParam(sig->GetParam(i)); | 
| +        } | 
| +        return index; | 
| +      } | 
| +    } | 
| +  }; | 
| + | 
| void VisitAssignment(Assignment* expr) { | 
| bool in_init = false; | 
| if (!in_function_) { | 
| // TODO(bradnelson): Get rid of this. | 
| if (TypeOf(expr->value()) == kAstStmt) { | 
| +        Property* prop = expr->value()->AsProperty(); | 
| +        if (prop != nullptr) { | 
| +          VariableProxy* vp = prop->obj()->AsVariableProxy(); | 
| +          if (vp != nullptr && vp->var()->IsParameter() && | 
| +              vp->var()->index() == 1) { | 
| +            VariableProxy* target = expr->target()->AsVariableProxy(); | 
| +            if (target->bounds().lower->Is(Type::Function())) { | 
| +              const AstRawString* name = | 
| +                  prop->key()->AsLiteral()->AsRawPropertyName(); | 
| +              imported_function_table_.AddImport( | 
| +                  target->var(), name->raw_data(), name->length()); | 
| +            } | 
| +          } | 
| +        } | 
| ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 
| if (funcs != nullptr && | 
| funcs->bounds().lower->AsArray()->Element()->IsFunction()) { | 
| @@ -620,8 +682,29 @@ class AsmWasmBuilderImpl : public AstVisitor { | 
| switch (call_type) { | 
| case Call::OTHER_CALL: { | 
| DCHECK(in_function_); | 
| +        uint16_t index; | 
| +        VariableProxy* vp = expr->expression()->AsVariableProxy(); | 
| +        if (vp != nullptr && | 
| +            Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { | 
| +          LocalType return_type = TypeOf(expr); | 
| +          ZoneList<Expression*>* args = expr->arguments(); | 
| +          FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 
| +                                   args->length()); | 
| +          if (return_type != kAstStmt) { | 
| +            sig.AddReturn(return_type); | 
| +          } | 
| +          for (int i = 0; i < args->length(); i++) { | 
| +            sig.AddParam(TypeOf(args->at(i))); | 
| +          } | 
| +          index = | 
| +              imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); | 
| +        } else { | 
| +          index = LookupOrInsertFunction(vp->var()); | 
| +        } | 
| current_function_builder_->Emit(kExprCallFunction); | 
| -        RECURSE(Visit(expr->expression())); | 
| +        std::vector<uint8_t> index_arr = UnsignedLEB128From(index); | 
| +        current_function_builder_->EmitCode( | 
| +            &index_arr[0], static_cast<uint32_t>(index_arr.size())); | 
| break; | 
| } | 
| case Call::KEYED_PROPERTY_CALL: { | 
| @@ -1094,6 +1177,7 @@ class AsmWasmBuilderImpl : public AstVisitor { | 
| uint16_t init_function_index_; | 
| uint32_t next_table_index_; | 
| ZoneHashMap function_tables_; | 
| +  ImportedFunctionTable imported_function_table_; | 
|  | 
| DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 
|  | 
|  |