| Index: src/wasm/encoder.cc | 
| diff --git a/src/wasm/encoder.cc b/src/wasm/encoder.cc | 
| index 3ae2213ce636f37d6fcfb672eeb78ce5aa17efac..39a2f5aeb5b47849a63a81e64a5f41f58b406451 100644 | 
| --- a/src/wasm/encoder.cc | 
| +++ b/src/wasm/encoder.cc | 
| @@ -95,18 +95,8 @@ byte* EmitSection(WasmSection::Code code, byte** b) { | 
| } | 
| }  // namespace | 
|  | 
| -struct WasmFunctionBuilder::Type { | 
| -  bool param_; | 
| -  LocalType type_; | 
| -}; | 
| - | 
| WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone) | 
| -    : return_type_(kAstI32), | 
| -      locals_(zone), | 
| -      exported_(0), | 
| -      body_(zone), | 
| -      local_indices_(zone), | 
| -      name_(zone) {} | 
| +    : locals_(zone), exported_(0), body_(zone), name_(zone) {} | 
|  | 
| void WasmFunctionBuilder::EmitVarInt(uint32_t val) { | 
| byte buffer[8]; | 
| @@ -117,45 +107,28 @@ void WasmFunctionBuilder::EmitVarInt(uint32_t val) { | 
| } | 
| } | 
|  | 
| -uint16_t WasmFunctionBuilder::AddParam(LocalType type) { | 
| -  return AddVar(type, true); | 
| -} | 
| - | 
| -uint16_t WasmFunctionBuilder::AddLocal(LocalType type) { | 
| -  return AddVar(type, false); | 
| +void WasmFunctionBuilder::SetSignature(FunctionSig* sig) { | 
| +  DCHECK(!locals_.has_sig()); | 
| +  locals_.set_sig(sig); | 
| } | 
|  | 
| -uint16_t WasmFunctionBuilder::AddVar(LocalType type, bool param) { | 
| -  locals_.push_back({param, type}); | 
| -  return static_cast<uint16_t>(locals_.size() - 1); | 
| -} | 
| - | 
| -void WasmFunctionBuilder::ReturnType(LocalType type) { return_type_ = type; } | 
| - | 
| -void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) { | 
| -  EmitCode(code, code_size, nullptr, 0); | 
| +uint32_t WasmFunctionBuilder::AddLocal(LocalType type) { | 
| +  DCHECK(locals_.has_sig()); | 
| +  return locals_.AddLocals(1, type); | 
| } | 
|  | 
| void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) { | 
| -  local_indices_.push_back(static_cast<uint32_t>(body_.size() + 1)); | 
| EmitWithVarInt(kExprGetLocal, local_index); | 
| } | 
|  | 
| void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) { | 
| -  local_indices_.push_back(static_cast<uint32_t>(body_.size() + 1)); | 
| EmitWithVarInt(kExprSetLocal, local_index); | 
| } | 
|  | 
| -void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size, | 
| -                                   const uint32_t* local_indices, | 
| -                                   uint32_t indices_size) { | 
| -  size_t size = body_.size(); | 
| +void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) { | 
| for (size_t i = 0; i < code_size; i++) { | 
| body_.push_back(code[i]); | 
| } | 
| -  for (size_t i = 0; i < indices_size; i++) { | 
| -    local_indices_.push_back(local_indices[i] + static_cast<uint32_t>(size)); | 
| -  } | 
| } | 
|  | 
| void WasmFunctionBuilder::Emit(WasmOpcode opcode) { | 
| @@ -190,35 +163,6 @@ void WasmFunctionBuilder::EmitI32Const(int32_t value) { | 
| } | 
| } | 
|  | 
| -uint32_t WasmFunctionBuilder::EmitEditableVarIntImmediate() { | 
| -  // Guess that the immediate will be 1 byte. If it is more, we'll have to | 
| -  // shift everything down. | 
| -  body_.push_back(0); | 
| -  return static_cast<uint32_t>(body_.size()) - 1; | 
| -} | 
| - | 
| -void WasmFunctionBuilder::EditVarIntImmediate(uint32_t offset, | 
| -                                              const uint32_t immediate) { | 
| -  uint32_t immediate_size = | 
| -      static_cast<uint32_t>(LEBHelper::sizeof_u32v(immediate)); | 
| -  // In EmitEditableVarIntImmediate, we guessed that we'd only need one byte. | 
| -  // If we need more, shift everything down to make room for the larger | 
| -  // immediate. | 
| -  if (immediate_size > 1) { | 
| -    uint32_t diff = immediate_size - 1; | 
| -    body_.insert(body_.begin() + offset, diff, 0); | 
| - | 
| -    for (size_t i = 0; i < local_indices_.size(); ++i) { | 
| -      if (local_indices_[i] >= offset) { | 
| -        local_indices_[i] += diff; | 
| -      } | 
| -    } | 
| -  } | 
| -  DCHECK(offset + immediate_size <= body_.size()); | 
| -  byte* p = &body_[offset]; | 
| -  v8::internal::wasm::EmitVarInt(&p, immediate); | 
| -} | 
| - | 
| void WasmFunctionBuilder::Exported(uint8_t flag) { exported_ = flag; } | 
|  | 
| void WasmFunctionBuilder::SetName(const char* name, int name_length) { | 
| @@ -233,102 +177,17 @@ void WasmFunctionBuilder::SetName(const char* name, int name_length) { | 
| WasmFunctionEncoder* WasmFunctionBuilder::Build(Zone* zone, | 
| WasmModuleBuilder* mb) const { | 
| WasmFunctionEncoder* e = | 
| -      new (zone) WasmFunctionEncoder(zone, return_type_, exported_); | 
| -  uint16_t* var_index = zone->NewArray<uint16_t>(locals_.size()); | 
| -  IndexVars(e, var_index); | 
| -  if (body_.size() > 0) { | 
| -    // TODO(titzer): iterate over local indexes, not the bytes. | 
| -    const byte* start = &body_[0]; | 
| -    size_t local_index = 0; | 
| -    for (size_t i = 0; i < body_.size();) { | 
| -      if (local_index < local_indices_.size() && | 
| -          i == local_indices_[local_index]) { | 
| -        // Read the old index. | 
| -        uint32_t index = 0; | 
| -        uint8_t b = 0; | 
| -        uint32_t shift = 0; | 
| -        while ((b = start[i++]) >= 0x80) { | 
| -          index |= (b & 0x7F) << shift; | 
| -          shift += 7; | 
| -        } | 
| -        index |= b << shift; | 
| - | 
| -        // Write the new index. | 
| -        uint16_t new_index = var_index[index]; | 
| -        while (new_index >= 0x80) { | 
| -          e->body_.push_back(new_index | 0x80); | 
| -          new_index >>= 7; | 
| -        } | 
| -        e->body_.push_back(new_index); | 
| - | 
| -        local_index++; | 
| -      } else { | 
| -        e->body_.push_back(*(start + i)); | 
| -        i++; | 
| -      } | 
| -    } | 
| -  } | 
| -  FunctionSig::Builder sig(zone, return_type_ == kAstStmt ? 0 : 1, | 
| -                           e->params_.size()); | 
| -  if (return_type_ != kAstStmt) { | 
| -    sig.AddReturn(static_cast<LocalType>(return_type_)); | 
| -  } | 
| -  for (size_t i = 0; i < e->params_.size(); i++) { | 
| -    sig.AddParam(static_cast<LocalType>(e->params_[i])); | 
| -  } | 
| -  e->signature_index_ = mb->AddSignature(sig.Build()); | 
| +      new (zone) WasmFunctionEncoder(zone, locals_, exported_); | 
| +  // TODO(titzer): lame memcpy here. | 
| +  e->body_.insert(e->body_.begin(), body_.begin(), body_.end()); | 
| +  e->signature_index_ = mb->AddSignature(locals_.get_sig()); | 
| e->name_.insert(e->name_.begin(), name_.begin(), name_.end()); | 
| return e; | 
| } | 
|  | 
| -void WasmFunctionBuilder::IndexVars(WasmFunctionEncoder* e, | 
| -                                    uint16_t* var_index) const { | 
| -  uint16_t param = 0; | 
| -  uint16_t i32 = 0; | 
| -  uint16_t i64 = 0; | 
| -  uint16_t f32 = 0; | 
| -  uint16_t f64 = 0; | 
| -  for (size_t i = 0; i < locals_.size(); i++) { | 
| -    if (locals_.at(i).param_) { | 
| -      param++; | 
| -    } else if (locals_.at(i).type_ == kAstI32) { | 
| -      i32++; | 
| -    } else if (locals_.at(i).type_ == kAstI64) { | 
| -      i64++; | 
| -    } else if (locals_.at(i).type_ == kAstF32) { | 
| -      f32++; | 
| -    } else if (locals_.at(i).type_ == kAstF64) { | 
| -      f64++; | 
| -    } | 
| -  } | 
| -  e->local_i32_count_ = i32; | 
| -  e->local_i64_count_ = i64; | 
| -  e->local_f32_count_ = f32; | 
| -  e->local_f64_count_ = f64; | 
| -  f64 = param + i32 + i64 + f32; | 
| -  f32 = param + i32 + i64; | 
| -  i64 = param + i32; | 
| -  i32 = param; | 
| -  param = 0; | 
| -  for (size_t i = 0; i < locals_.size(); i++) { | 
| -    if (locals_.at(i).param_) { | 
| -      e->params_.push_back(locals_.at(i).type_); | 
| -      var_index[i] = param++; | 
| -    } else if (locals_.at(i).type_ == kAstI32) { | 
| -      var_index[i] = i32++; | 
| -    } else if (locals_.at(i).type_ == kAstI64) { | 
| -      var_index[i] = i64++; | 
| -    } else if (locals_.at(i).type_ == kAstF32) { | 
| -      var_index[i] = f32++; | 
| -    } else if (locals_.at(i).type_ == kAstF64) { | 
| -      var_index[i] = f64++; | 
| -    } | 
| -  } | 
| -} | 
| - | 
| -WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalType return_type, | 
| +WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalDeclEncoder locals, | 
| bool exported) | 
| -    : params_(zone), exported_(exported), body_(zone), name_(zone) {} | 
| +    : locals_(locals), exported_(exported), body_(zone), name_(zone) {} | 
|  | 
| uint32_t WasmFunctionEncoder::HeaderSize() const { | 
| uint32_t size = 3; | 
| @@ -342,14 +201,7 @@ uint32_t WasmFunctionEncoder::HeaderSize() const { | 
| } | 
|  | 
| uint32_t WasmFunctionEncoder::BodySize(void) const { | 
| -  // TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder | 
| -  LocalDeclEncoder local_decl; | 
| -  local_decl.AddLocals(local_i32_count_, kAstI32); | 
| -  local_decl.AddLocals(local_i64_count_, kAstI64); | 
| -  local_decl.AddLocals(local_f32_count_, kAstF32); | 
| -  local_decl.AddLocals(local_f64_count_, kAstF64); | 
| - | 
| -  return static_cast<uint32_t>(body_.size() + local_decl.Size()); | 
| +  return static_cast<uint32_t>(body_.size() + locals_.Size()); | 
| } | 
|  | 
| uint32_t WasmFunctionEncoder::NameSize() const { | 
| @@ -371,15 +223,8 @@ void WasmFunctionEncoder::Serialize(byte* buffer, byte** header, | 
| } | 
| } | 
|  | 
| -  // TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder | 
| -  LocalDeclEncoder local_decl; | 
| -  local_decl.AddLocals(local_i32_count_, kAstI32); | 
| -  local_decl.AddLocals(local_i64_count_, kAstI64); | 
| -  local_decl.AddLocals(local_f32_count_, kAstF32); | 
| -  local_decl.AddLocals(local_f64_count_, kAstF64); | 
| - | 
| -  EmitUint16(header, static_cast<uint16_t>(body_.size() + local_decl.Size())); | 
| -  (*header) += local_decl.Emit(*header); | 
| +  EmitUint16(header, static_cast<uint16_t>(body_.size() + locals_.Size())); | 
| +  (*header) += locals_.Emit(*header); | 
| if (body_.size() > 0) { | 
| std::memcpy(*header, &body_[0], body_.size()); | 
| (*header) += body_.size(); | 
| @@ -462,14 +307,14 @@ uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) { | 
| if (pos != signature_map_.end()) { | 
| return pos->second; | 
| } else { | 
| -    uint16_t index = static_cast<uint16_t>(signatures_.size()); | 
| +    uint32_t index = static_cast<uint32_t>(signatures_.size()); | 
| signature_map_[sig] = index; | 
| signatures_.push_back(sig); | 
| return index; | 
| } | 
| } | 
|  | 
| -void WasmModuleBuilder::AddIndirectFunction(uint16_t index) { | 
| +void WasmModuleBuilder::AddIndirectFunction(uint32_t index) { | 
| indirect_functions_.push_back(index); | 
| } | 
|  | 
| @@ -479,7 +324,7 @@ uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, | 
| return static_cast<uint32_t>(imports_.size() - 1); | 
| } | 
|  | 
| -void WasmModuleBuilder::MarkStartFunction(uint16_t index) { | 
| +void WasmModuleBuilder::MarkStartFunction(uint32_t index) { | 
| start_function_index_ = index; | 
| } | 
|  | 
|  |