Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE

This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.

FPIIM-449

Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc
index fd24280..02d197c 100644
--- a/src/wasm/wasm-module.cc
+++ b/src/wasm/wasm-module.cc
@@ -31,33 +31,32 @@
 
 
 std::ostream& operator<<(std::ostream& os, const WasmFunction& function) {
-  os << "WASM function with signature ";
+  os << "WASM function with signature " << *function.sig;
 
-  // TODO(titzer): factor out rendering of signatures.
-  if (function.sig->return_count() == 0) os << "v";
-  for (size_t i = 0; i < function.sig->return_count(); i++) {
-    os << WasmOpcodes::ShortNameOf(function.sig->GetReturn(i));
-  }
-  os << "_";
-  if (function.sig->parameter_count() == 0) os << "v";
-  for (size_t i = 0; i < function.sig->parameter_count(); i++) {
-    os << WasmOpcodes::ShortNameOf(function.sig->GetParam(i));
-  }
   os << " locals: ";
-  if (function.local_int32_count)
-    os << function.local_int32_count << " int32s ";
-  if (function.local_int64_count)
-    os << function.local_int64_count << " int64s ";
-  if (function.local_float32_count)
-    os << function.local_float32_count << " float32s ";
-  if (function.local_float64_count)
-    os << function.local_float64_count << " float64s ";
+  if (function.local_i32_count) os << function.local_i32_count << " i32s ";
+  if (function.local_i64_count) os << function.local_i64_count << " i64s ";
+  if (function.local_f32_count) os << function.local_f32_count << " f32s ";
+  if (function.local_f64_count) os << function.local_f64_count << " f64s ";
 
   os << " code bytes: "
      << (function.code_end_offset - function.code_start_offset);
   return os;
 }
 
+std::ostream& operator<<(std::ostream& os, const WasmFunctionName& pair) {
+  os << "#" << pair.function_->func_index << ":";
+  if (pair.function_->name_offset > 0) {
+    if (pair.module_) {
+      os << pair.module_->GetName(pair.function_->name_offset);
+    } else {
+      os << "+" << pair.function_->func_index;
+    }
+  } else {
+    os << "?";
+  }
+  return os;
+}
 
 // A helper class for compiling multiple wasm functions that offers
 // placeholder code objects for calling functions that are not yet compiled.
@@ -193,35 +192,98 @@
   return fixed;
 }
 
-
-Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, int size,
+Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size,
                                      byte** backing_store) {
-  void* memory = isolate->array_buffer_allocator()->Allocate(size);
-  if (!memory) return Handle<JSArrayBuffer>::null();
+  if (size > (1 << WasmModule::kMaxMemSize)) {
+    // TODO(titzer): lift restriction on maximum memory allocated here.
+    *backing_store = nullptr;
+    return Handle<JSArrayBuffer>::null();
+  }
+  void* memory =
+      isolate->array_buffer_allocator()->Allocate(static_cast<int>(size));
+  if (!memory) {
+    *backing_store = nullptr;
+    return Handle<JSArrayBuffer>::null();
+  }
+
   *backing_store = reinterpret_cast<byte*>(memory);
 
 #if DEBUG
   // Double check the API allocator actually zero-initialized the memory.
-  for (int i = 0; i < size; i++) {
-    DCHECK_EQ(0, (*backing_store)[i]);
+  byte* bytes = reinterpret_cast<byte*>(*backing_store);
+  for (size_t i = 0; i < size; i++) {
+    DCHECK_EQ(0, bytes[i]);
   }
 #endif
 
   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
-  JSArrayBuffer::Setup(buffer, isolate, false, memory, size);
+  JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size));
   buffer->set_is_neuterable(false);
   return buffer;
 }
+
+// Set the memory for a module instance to be the {memory} array buffer.
+void SetMemory(WasmModuleInstance* instance, Handle<JSArrayBuffer> memory) {
+  memory->set_is_neuterable(false);
+  instance->mem_start = reinterpret_cast<byte*>(memory->backing_store());
+  instance->mem_size = memory->byte_length()->Number();
+  instance->mem_buffer = memory;
+}
+
+// Allocate memory for a module instance as a new JSArrayBuffer.
+bool AllocateMemory(ErrorThrower* thrower, Isolate* isolate,
+                    WasmModuleInstance* instance) {
+  DCHECK(instance->module);
+  DCHECK(instance->mem_buffer.is_null());
+
+  if (instance->module->min_mem_size_log2 > WasmModule::kMaxMemSize) {
+    thrower->Error("Out of memory: wasm memory too large");
+    return false;
+  }
+  instance->mem_size = static_cast<size_t>(1)
+                       << instance->module->min_mem_size_log2;
+  instance->mem_buffer =
+      NewArrayBuffer(isolate, instance->mem_size, &instance->mem_start);
+  if (!instance->mem_start) {
+    thrower->Error("Out of memory: wasm memory");
+    instance->mem_size = 0;
+    return false;
+  }
+  return true;
+}
+
+bool AllocateGlobals(ErrorThrower* thrower, Isolate* isolate,
+                     WasmModuleInstance* instance) {
+  instance->globals_size = AllocateGlobalsOffsets(instance->module->globals);
+
+  if (instance->globals_size > 0) {
+    instance->globals_buffer = NewArrayBuffer(isolate, instance->globals_size,
+                                              &instance->globals_start);
+    if (!instance->globals_start) {
+      // Not enough space for backing store of globals.
+      thrower->Error("Out of memory: wasm globals");
+      return false;
+    }
+  }
+  return true;
+}
 }  // namespace
 
-
 WasmModule::WasmModule()
-    : globals(nullptr),
+    : shared_isolate(nullptr),
+      module_start(nullptr),
+      module_end(nullptr),
+      min_mem_size_log2(0),
+      max_mem_size_log2(0),
+      mem_export(false),
+      mem_external(false),
+      start_function_index(-1),
+      globals(nullptr),
       signatures(nullptr),
       functions(nullptr),
       data_segments(nullptr),
-      function_table(nullptr) {}
-
+      function_table(nullptr),
+      import_table(nullptr) {}
 
 WasmModule::~WasmModule() {
   if (globals) delete globals;
@@ -229,8 +291,33 @@
   if (functions) delete functions;
   if (data_segments) delete data_segments;
   if (function_table) delete function_table;
+  if (import_table) delete import_table;
 }
 
+static MaybeHandle<JSFunction> LookupFunction(ErrorThrower& thrower,
+                                              Handle<JSObject> ffi,
+                                              uint32_t index,
+                                              Handle<String> name,
+                                              const char* cstr) {
+  if (!ffi.is_null()) {
+    MaybeHandle<Object> result = Object::GetProperty(ffi, name);
+    if (!result.is_null()) {
+      Handle<Object> obj = result.ToHandleChecked();
+      if (obj->IsJSFunction()) {
+        return Handle<JSFunction>::cast(obj);
+      } else {
+        thrower.Error("FFI function #%d:%s is not a JSFunction.", index, cstr);
+        return MaybeHandle<JSFunction>();
+      }
+    } else {
+      thrower.Error("FFI function #%d:%s not found.", index, cstr);
+      return MaybeHandle<JSFunction>();
+    }
+  } else {
+    thrower.Error("FFI table is not an object.");
+    return MaybeHandle<JSFunction>();
+  }
+}
 
 // Instantiates a wasm module as a JSObject.
 //  * allocates a backing store of {mem_size} bytes.
@@ -242,95 +329,91 @@
                                               Handle<JSArrayBuffer> memory) {
   this->shared_isolate = isolate;  // TODO(titzer): have a real shared isolate.
   ErrorThrower thrower(isolate, "WasmModule::Instantiate()");
-
   Factory* factory = isolate->factory();
-  // Memory is bigger than maximum supported size.
-  if (memory.is_null() && min_mem_size_log2 > kMaxMemSize) {
-    thrower.Error("Out of memory: wasm memory too large");
-    return MaybeHandle<JSObject>();
-  }
 
+  //-------------------------------------------------------------------------
+  // Allocate the instance and its JS counterpart.
+  //-------------------------------------------------------------------------
   Handle<Map> map = factory->NewMap(
       JS_OBJECT_TYPE,
       JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize);
-
-  //-------------------------------------------------------------------------
-  // Allocate the module object.
-  //-------------------------------------------------------------------------
-  Handle<JSObject> module = factory->NewJSObjectFromMap(map, TENURED);
+  WasmModuleInstance instance(this);
+  std::vector<Handle<Code>> import_code;
+  instance.context = isolate->native_context();
+  instance.js_object = factory->NewJSObjectFromMap(map, TENURED);
   Handle<FixedArray> code_table =
       factory->NewFixedArray(static_cast<int>(functions->size()), TENURED);
+  instance.js_object->SetInternalField(kWasmModuleCodeTable, *code_table);
 
   //-------------------------------------------------------------------------
-  // Allocate the linear memory.
+  // Allocate and initialize the linear memory.
   //-------------------------------------------------------------------------
-  uint32_t mem_size = 1 << min_mem_size_log2;
-  byte* mem_addr = nullptr;
-  Handle<JSArrayBuffer> mem_buffer;
-  if (!memory.is_null()) {
-    memory->set_is_neuterable(false);
-    mem_addr = reinterpret_cast<byte*>(memory->backing_store());
-    mem_size = memory->byte_length()->Number();
-    mem_buffer = memory;
-  } else {
-    mem_buffer = NewArrayBuffer(isolate, mem_size, &mem_addr);
-    if (!mem_addr) {
-      // Not enough space for backing store of memory
-      thrower.Error("Out of memory: wasm memory");
+  if (memory.is_null()) {
+    if (!AllocateMemory(&thrower, isolate, &instance)) {
       return MaybeHandle<JSObject>();
     }
+  } else {
+    SetMemory(&instance, memory);
   }
-
-  // Load initialized data segments.
-  LoadDataSegments(this, mem_addr, mem_size);
-
-  module->SetInternalField(kWasmMemArrayBuffer, *mem_buffer);
+  instance.js_object->SetInternalField(kWasmMemArrayBuffer,
+                                       *instance.mem_buffer);
+  LoadDataSegments(this, instance.mem_start, instance.mem_size);
 
   if (mem_export) {
     // Export the memory as a named property.
     Handle<String> name = factory->InternalizeUtf8String("memory");
-    JSObject::AddProperty(module, name, mem_buffer, READ_ONLY);
+    JSObject::AddProperty(instance.js_object, name, instance.mem_buffer,
+                          READ_ONLY);
   }
 
   //-------------------------------------------------------------------------
   // Allocate the globals area if necessary.
   //-------------------------------------------------------------------------
-  size_t globals_size = AllocateGlobalsOffsets(globals);
-  byte* globals_addr = nullptr;
-  if (globals_size > 0) {
-    Handle<JSArrayBuffer> globals_buffer =
-        NewArrayBuffer(isolate, mem_size, &globals_addr);
-    if (!globals_addr) {
-      // Not enough space for backing store of globals.
-      thrower.Error("Out of memory: wasm globals");
-      return MaybeHandle<JSObject>();
-    }
+  if (!AllocateGlobals(&thrower, isolate, &instance)) {
+    return MaybeHandle<JSObject>();
+  }
+  if (!instance.globals_buffer.is_null()) {
+    instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer,
+                                         *instance.globals_buffer);
+  }
 
-    module->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer);
-  } else {
-    module->SetInternalField(kWasmGlobalsArrayBuffer, Smi::FromInt(0));
+  //-------------------------------------------------------------------------
+  // Compile wrappers to imported functions.
+  //-------------------------------------------------------------------------
+  uint32_t index = 0;
+  instance.function_table = BuildFunctionTable(isolate, this);
+  WasmLinker linker(isolate, functions->size());
+  ModuleEnv module_env;
+  module_env.module = this;
+  module_env.instance = &instance;
+  module_env.linker = &linker;
+  module_env.asm_js = false;
+
+  if (import_table->size() > 0) {
+    instance.import_code = &import_code;
+    instance.import_code->reserve(import_table->size());
+    for (const WasmImport& import : *import_table) {
+      const char* cstr = GetName(import.function_name_offset);
+      Handle<String> name = factory->InternalizeUtf8String(cstr);
+      MaybeHandle<JSFunction> function =
+          LookupFunction(thrower, ffi, index, name, cstr);
+      if (function.is_null()) return MaybeHandle<JSObject>();
+      Handle<Code> code = compiler::CompileWasmToJSWrapper(
+          isolate, &module_env, function.ToHandleChecked(), import.sig, cstr);
+      instance.import_code->push_back(code);
+      index++;
+    }
   }
 
   //-------------------------------------------------------------------------
   // Compile all functions in the module.
   //-------------------------------------------------------------------------
-  int index = 0;
-  WasmLinker linker(isolate, functions->size());
-  ModuleEnv module_env;
-  module_env.module = this;
-  module_env.mem_start = reinterpret_cast<uintptr_t>(mem_addr);
-  module_env.mem_end = reinterpret_cast<uintptr_t>(mem_addr) + mem_size;
-  module_env.globals_area = reinterpret_cast<uintptr_t>(globals_addr);
-  module_env.linker = &linker;
-  module_env.function_code = nullptr;
-  module_env.function_table = BuildFunctionTable(isolate, this);
-  module_env.memory = memory;
-  module_env.context = isolate->native_context();
-  module_env.asm_js = false;
 
   // First pass: compile each function and initialize the code table.
+  index = 0;
   for (const WasmFunction& func : *functions) {
     if (thrower.error()) break;
+    DCHECK_EQ(index, func.func_index);
 
     const char* cstr = GetName(func.name_offset);
     Handle<String> name = factory->InternalizeUtf8String(cstr);
@@ -338,38 +421,21 @@
     Handle<JSFunction> function = Handle<JSFunction>::null();
     if (func.external) {
       // Lookup external function in FFI object.
-      if (!ffi.is_null()) {
-        MaybeHandle<Object> result = Object::GetProperty(ffi, name);
-        if (!result.is_null()) {
-          Handle<Object> obj = result.ToHandleChecked();
-          if (obj->IsJSFunction()) {
-            function = Handle<JSFunction>::cast(obj);
-            code = compiler::CompileWasmToJSWrapper(isolate, &module_env,
-                                                    function, index);
-          } else {
-            thrower.Error("FFI function #%d:%s is not a JSFunction.", index,
-                          cstr);
-            return MaybeHandle<JSObject>();
-          }
-        } else {
-          thrower.Error("FFI function #%d:%s not found.", index, cstr);
-          return MaybeHandle<JSObject>();
-        }
-      } else {
-        thrower.Error("FFI table is not an object.");
-        return MaybeHandle<JSObject>();
-      }
+      MaybeHandle<JSFunction> function =
+          LookupFunction(thrower, ffi, index, name, cstr);
+      if (function.is_null()) return MaybeHandle<JSObject>();
+      code = compiler::CompileWasmToJSWrapper(
+          isolate, &module_env, function.ToHandleChecked(), func.sig, cstr);
     } else {
       // Compile the function.
-      code = compiler::CompileWasmFunction(thrower, isolate, &module_env, func,
-                                           index);
+      code = compiler::CompileWasmFunction(thrower, isolate, &module_env, func);
       if (code.is_null()) {
         thrower.Error("Compilation of #%d:%s failed.", index, cstr);
         return MaybeHandle<JSObject>();
       }
       if (func.exported) {
-        function = compiler::CompileJSToWasmWrapper(isolate, &module_env, name,
-                                                    code, module, index);
+        function = compiler::CompileJSToWasmWrapper(
+            isolate, &module_env, name, code, instance.js_object, index);
       }
     }
     if (!code.is_null()) {
@@ -379,27 +445,54 @@
     }
     if (func.exported) {
       // Exported functions are installed as read-only properties on the module.
-      JSObject::AddProperty(module, name, function, READ_ONLY);
+      JSObject::AddProperty(instance.js_object, name, function, READ_ONLY);
     }
     index++;
   }
 
   // Second pass: patch all direct call sites.
-  linker.Link(module_env.function_table, this->function_table);
+  linker.Link(instance.function_table, this->function_table);
+  instance.js_object->SetInternalField(kWasmModuleFunctionTable,
+                                       Smi::FromInt(0));
 
-  module->SetInternalField(kWasmModuleFunctionTable, Smi::FromInt(0));
-  module->SetInternalField(kWasmModuleCodeTable, *code_table);
-  return module;
+  // Run the start function if one was specified.
+  if (this->start_function_index >= 0) {
+    HandleScope scope(isolate);
+    uint32_t index = static_cast<uint32_t>(this->start_function_index);
+    Handle<String> name = isolate->factory()->NewStringFromStaticChars("start");
+    Handle<Code> code = linker.GetFunctionCode(index);
+    Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper(
+        isolate, &module_env, name, code, instance.js_object, index);
+
+    // Call the JS function.
+    Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
+    MaybeHandle<Object> retval =
+        Execution::Call(isolate, jsfunc, undefined, 0, nullptr);
+
+    if (retval.is_null()) {
+      thrower.Error("WASM.instantiateModule(): start function failed");
+    }
+  }
+  return instance.js_object;
 }
 
 
 Handle<Code> ModuleEnv::GetFunctionCode(uint32_t index) {
   DCHECK(IsValidFunction(index));
   if (linker) return linker->GetFunctionCode(index);
-  if (function_code) return function_code->at(index);
+  if (instance && instance->function_code) {
+    return instance->function_code->at(index);
+  }
   return Handle<Code>::null();
 }
 
+Handle<Code> ModuleEnv::GetImportCode(uint32_t index) {
+  DCHECK(IsValidImport(index));
+  if (instance && instance->import_code) {
+    return instance->import_code->at(index);
+  }
+  return Handle<Code>::null();
+}
 
 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone,
                                                        uint32_t index) {
@@ -436,43 +529,45 @@
 
 int32_t CompileAndRunWasmModule(Isolate* isolate, WasmModule* module) {
   ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
+  WasmModuleInstance instance(module);
 
-  // Allocate temporary linear memory and globals.
-  size_t mem_size = 1 << module->min_mem_size_log2;
-  size_t globals_size = AllocateGlobalsOffsets(module->globals);
+  // Allocate and initialize the linear memory.
+  if (!AllocateMemory(&thrower, isolate, &instance)) {
+    return -1;
+  }
+  LoadDataSegments(module, instance.mem_start, instance.mem_size);
 
-  base::SmartArrayPointer<byte> mem_addr(new byte[mem_size]);
-  base::SmartArrayPointer<byte> globals_addr(new byte[globals_size]);
+  // Allocate the globals area if necessary.
+  if (!AllocateGlobals(&thrower, isolate, &instance)) {
+    return -1;
+  }
 
-  memset(mem_addr.get(), 0, mem_size);
-  memset(globals_addr.get(), 0, globals_size);
+  // Build the function table.
+  instance.function_table = BuildFunctionTable(isolate, module);
 
   // Create module environment.
   WasmLinker linker(isolate, module->functions->size());
   ModuleEnv module_env;
   module_env.module = module;
-  module_env.mem_start = reinterpret_cast<uintptr_t>(mem_addr.get());
-  module_env.mem_end = reinterpret_cast<uintptr_t>(mem_addr.get()) + mem_size;
-  module_env.globals_area = reinterpret_cast<uintptr_t>(globals_addr.get());
+  module_env.instance = &instance;
   module_env.linker = &linker;
-  module_env.function_code = nullptr;
-  module_env.function_table = BuildFunctionTable(isolate, module);
   module_env.asm_js = false;
 
-  // Load data segments.
-  // TODO(titzer): throw instead of crashing if segments don't fit in memory?
-  LoadDataSegments(module, mem_addr.get(), mem_size);
-
   // Compile all functions.
   Handle<Code> main_code = Handle<Code>::null();  // record last code.
-  int index = 0;
+  uint32_t index = 0;
+  int main_index = 0;
   for (const WasmFunction& func : *module->functions) {
+    DCHECK_EQ(index, func.func_index);
     if (!func.external) {
       // Compile the function and install it in the code table.
-      Handle<Code> code = compiler::CompileWasmFunction(
-          thrower, isolate, &module_env, func, index);
+      Handle<Code> code =
+          compiler::CompileWasmFunction(thrower, isolate, &module_env, func);
       if (!code.is_null()) {
-        if (func.exported) main_code = code;
+        if (func.exported) {
+          main_code = code;
+          main_index = index;
+        }
         linker.Finish(index, code);
       }
       if (thrower.error()) return -1;
@@ -480,30 +575,37 @@
     index++;
   }
 
-  if (!main_code.is_null()) {
-    linker.Link(module_env.function_table, module->function_table);
-#if USE_SIMULATOR && V8_TARGET_ARCH_ARM64
-    // Run the main code on arm64 simulator.
-    Simulator* simulator = Simulator::current(isolate);
-    Simulator::CallArgument args[] = {Simulator::CallArgument(0),
-                                      Simulator::CallArgument::End()};
-    return static_cast<int32_t>(simulator->CallInt64(main_code->entry(), args));
-#elif USE_SIMULATOR
-    // Run the main code on simulator.
-    Simulator* simulator = Simulator::current(isolate);
-    return static_cast<int32_t>(
-        simulator->Call(main_code->entry(), 4, 0, 0, 0, 0));
-#else
-    // Run the main code as raw machine code.
-    int32_t (*raw_func)() = reinterpret_cast<int32_t (*)()>(
-        reinterpret_cast<uintptr_t>(main_code->entry()));
-    return raw_func();
-#endif
-  } else {
-    // No main code was found.
-    isolate->Throw(*isolate->factory()->NewStringFromStaticChars(
-        "WASM.compileRun() failed: no valid main code produced."));
+  if (main_code.is_null()) {
+    thrower.Error("WASM.compileRun() failed: no main code found");
+    return -1;
   }
+
+  linker.Link(instance.function_table, instance.module->function_table);
+
+  // Wrap the main code so it can be called as a JS function.
+  Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
+  Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
+  Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper(
+      isolate, &module_env, name, main_code, module_object, main_index);
+
+  // Call the JS function.
+  Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
+  MaybeHandle<Object> retval =
+      Execution::Call(isolate, jsfunc, undefined, 0, nullptr);
+
+  // The result should be a number.
+  if (retval.is_null()) {
+    thrower.Error("WASM.compileRun() failed: Invocation was null");
+    return -1;
+  }
+  Handle<Object> result = retval.ToHandleChecked();
+  if (result->IsSmi()) {
+    return Smi::cast(*result)->value();
+  }
+  if (result->IsHeapNumber()) {
+    return static_cast<int32_t>(HeapNumber::cast(*result)->value());
+  }
+  thrower.Error("WASM.compileRun() failed: Return value should be number");
   return -1;
 }
 }  // namespace wasm