optimize
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index ba3be7b..bf35944 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1405,11 +1405,11 @@
   Signature getSignatureByFunctionIndex(Index index);
   Signature getSignatureByTypeIndex(Index index);
 
-  // The heap types of functions. This is cached for performance reasons, as
-  // computing the heap type from the signature (stored in functionSignatures)
-  // is not cheap.
+  // Cache a mapping of signatures to heap types. This lets us get the heap
+  // type of a function very efficiently, as computing the heap type from the
+  // signature (stored in functionSignatures) is not cheap.
   // TODO: optimize that conversion and remove this
-  std::vector<HeapType> functionTypes;
+  std::unordered_map<Signature, HeapType> signatureTypes;
 
   HeapType getTypeByFunctionIndex(Index index);
 
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index c842fbf..5dad261 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -2113,15 +2113,12 @@
 }
 
 HeapType WasmBinaryBuilder::getTypeByFunctionIndex(Index index) {
-  // functionTypes is grown on demand, and contains HeapType::any for
-  // uninitialized elements, which we lazily fill.
-  if (functionTypes.size() <= index) {
-    functionTypes.resize(index + 1, HeapType::any);
+  auto sig = getSignatureByFunctionIndex(index);
+  auto iter = signatureTypes.find(sig);
+  if (iter != signatureTypes.end()) {
+    return iter->second;
   }
-  if (functionTypes[index] != HeapType::any) {
-    return functionTypes[index];
-  }
-  return functionTypes[index] = HeapType(getSignatureByFunctionIndex(index));
+  return signatureTypes[sig] = HeapType(sig);
 }
 
 void WasmBinaryBuilder::readFunctions() {