Merge V8 5.3.332.45.  DO NOT MERGE

Test: Manual

FPIIM-449

Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h
index a92c9ff..1f758bb 100644
--- a/test/cctest/wasm/wasm-run-utils.h
+++ b/test/cctest/wasm/wasm-run-utils.h
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "src/base/accounting-allocator.h"
 #include "src/base/utils/random-number-generator.h"
 
 #include "src/compiler/graph-visualizer.h"
@@ -20,6 +21,7 @@
 #include "src/compiler/zone-pool.h"
 
 #include "src/wasm/ast-decoder.h"
+#include "src/wasm/wasm-interpreter.h"
 #include "src/wasm/wasm-js.h"
 #include "src/wasm/wasm-macro-gen.h"
 #include "src/wasm/wasm-module.h"
@@ -31,15 +33,10 @@
 #include "test/cctest/compiler/call-tester.h"
 #include "test/cctest/compiler/graph-builder-tester.h"
 
-// TODO(titzer): pull WASM_64 up to a common header.
-#if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
-#define WASM_64 1
-#else
-#define WASM_64 0
-#endif
-
 static const uint32_t kMaxFunctions = 10;
 
+enum WasmExecutionMode { kExecuteInterpreted, kExecuteCompiled };
+
 // TODO(titzer): check traps more robustly in tests.
 // Currently, in tests, we just return 0xdeadbeef from the function in which
 // the trap occurs if the runtime context is not available to throw a JavaScript
@@ -72,16 +69,21 @@
 // {WasmModuleInstance}.
 class TestingModule : public ModuleEnv {
  public:
-  TestingModule() : instance_(&module_), global_offset(0) {
-    module_.shared_isolate = CcTest::InitIsolateOnce();
+  explicit TestingModule(WasmExecutionMode mode = kExecuteCompiled)
+      : execution_mode_(mode),
+        instance_(&module_),
+        isolate_(CcTest::InitIsolateOnce()),
+        global_offset(0),
+        interpreter_(mode == kExecuteInterpreted
+                         ? new WasmInterpreter(&instance_, &allocator_)
+                         : nullptr) {
     module = &module_;
     instance = &instance_;
     instance->module = &module_;
     instance->globals_start = global_data;
-    instance->globals_size = kMaxGlobalsSize;
+    module_.globals_size = kMaxGlobalsSize;
     instance->mem_start = nullptr;
     instance->mem_size = 0;
-    linker = nullptr;
     origin = kWasmOrigin;
     memset(global_data, 0, sizeof(global_data));
   }
@@ -90,9 +92,10 @@
     if (instance->mem_start) {
       free(instance->mem_start);
     }
+    if (interpreter_) delete interpreter_;
   }
 
-  byte* AddMemory(size_t size) {
+  byte* AddMemory(uint32_t size) {
     CHECK_NULL(instance->mem_start);
     CHECK_EQ(0, instance->mem_size);
     instance->mem_start = reinterpret_cast<byte*>(malloc(size));
@@ -103,19 +106,19 @@
   }
 
   template <typename T>
-  T* AddMemoryElems(size_t count) {
+  T* AddMemoryElems(uint32_t count) {
     AddMemory(count * sizeof(T));
     return raw_mem_start<T>();
   }
 
   template <typename T>
   T* AddGlobal(MachineType mem_type) {
-    WasmGlobal* global = AddGlobal(mem_type);
+    const WasmGlobal* global = AddGlobal(mem_type);
     return reinterpret_cast<T*>(instance->globals_start + global->offset);
   }
 
   byte AddSignature(FunctionSig* sig) {
-    module->signatures.push_back(sig);
+    module_.signatures.push_back(sig);
     size_t size = module->signatures.size();
     CHECK(size < 127);
     return static_cast<byte>(size - 1);
@@ -165,11 +168,16 @@
     if (module->functions.size() == 0) {
       // TODO(titzer): Reserving space here to avoid the underlying WasmFunction
       // structs from moving.
-      module->functions.reserve(kMaxFunctions);
+      module_.functions.reserve(kMaxFunctions);
     }
     uint32_t index = static_cast<uint32_t>(module->functions.size());
-    module->functions.push_back({sig, index, 0, 0, 0, 0, 0, false});
+    module_.functions.push_back({sig, index, 0, 0, 0, 0, 0});
     instance->function_code.push_back(code);
+    if (interpreter_) {
+      const WasmFunction* function = &module->functions.back();
+      int interpreter_index = interpreter_->AddFunctionForTesting(function);
+      CHECK_EQ(index, static_cast<uint32_t>(interpreter_index));
+    }
     DCHECK_LT(index, kMaxFunctions);  // limited for testing.
     return index;
   }
@@ -178,23 +186,21 @@
     Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
         *v8::Local<v8::Function>::Cast(CompileRun(source))));
     uint32_t index = AddFunction(sig, Handle<Code>::null());
-    Isolate* isolate = module->shared_isolate;
     WasmName module_name = ArrayVector("test");
     WasmName function_name;
-    Handle<Code> code = CompileWasmToJSWrapper(isolate, this, jsfunc, sig,
+    Handle<Code> code = CompileWasmToJSWrapper(isolate_, jsfunc, sig,
                                                module_name, function_name);
     instance->function_code[index] = code;
     return index;
   }
 
   Handle<JSFunction> WrapCode(uint32_t index) {
-    Isolate* isolate = module->shared_isolate;
     // Wrap the 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<String> name = isolate_->factory()->NewStringFromStaticChars("main");
+    Handle<JSObject> module_object = Handle<JSObject>(0, isolate_);
     Handle<Code> code = instance->function_code[index];
-    WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
-    return compiler::CompileJSToWasmWrapper(isolate, this, name, code,
+    WasmJs::InstallWasmFunctionMap(isolate_, isolate_->native_context());
+    return compiler::CompileJSToWasmWrapper(isolate_, this, name, code,
                                             module_object, index);
   }
 
@@ -203,13 +209,12 @@
   }
 
   void AddIndirectFunctionTable(int* functions, int table_size) {
-    Isolate* isolate = module->shared_isolate;
     Handle<FixedArray> fixed =
-        isolate->factory()->NewFixedArray(2 * table_size);
+        isolate_->factory()->NewFixedArray(2 * table_size);
     instance->function_table = fixed;
     DCHECK_EQ(0u, module->function_table.size());
     for (int i = 0; i < table_size; i++) {
-      module->function_table.push_back(functions[i]);
+      module_.function_table.push_back(functions[i]);
     }
   }
 
@@ -218,23 +223,31 @@
     int table_size = static_cast<int>(module->function_table.size());
     for (int i = 0; i < table_size; i++) {
       int function_index = module->function_table[i];
-      WasmFunction* function = &module->functions[function_index];
+      const WasmFunction* function = &module->functions[function_index];
       instance->function_table->set(i, Smi::FromInt(function->sig_index));
       instance->function_table->set(i + table_size,
                                     *instance->function_code[function_index]);
     }
   }
+  WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; }
+
+  WasmInterpreter* interpreter() { return interpreter_; }
+  WasmExecutionMode execution_mode() { return execution_mode_; }
 
  private:
+  WasmExecutionMode execution_mode_;
   WasmModule module_;
   WasmModuleInstance instance_;
+  Isolate* isolate_;
+  v8::base::AccountingAllocator allocator_;
   uint32_t global_offset;
   V8_ALIGNED(8) byte global_data[kMaxGlobalsSize];  // preallocated global data.
+  WasmInterpreter* interpreter_;
 
-  WasmGlobal* AddGlobal(MachineType mem_type) {
+  const WasmGlobal* AddGlobal(MachineType mem_type) {
     byte size = WasmOpcodes::MemSize(mem_type);
     global_offset = (global_offset + size - 1) & ~(size - 1);  // align
-    module->globals.push_back({0, 0, mem_type, global_offset, false});
+    module_.globals.push_back({0, 0, mem_type, global_offset, false});
     global_offset += size;
     // limit number of globals.
     CHECK_LT(global_offset, kMaxGlobalsSize);
@@ -408,14 +421,41 @@
 // A helper for compiling WASM functions for testing. This class can create a
 // standalone function if {module} is NULL or a function within a
 // {TestingModule}. It contains the internal state for compilation (i.e.
-// TurboFan graph) and, later, interpretation.
+// TurboFan graph) and interpretation (by adding to the interpreter manually).
 class WasmFunctionCompiler : public HandleAndZoneScope,
                              private GraphAndBuilders {
  public:
   explicit WasmFunctionCompiler(
+      FunctionSig* sig, WasmExecutionMode mode,
+      Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
+      : GraphAndBuilders(main_zone()),
+        execution_mode_(mode),
+        jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
+                nullptr, this->machine()),
+        sig(sig),
+        descriptor_(nullptr),
+        testing_module_(nullptr),
+        debug_name_(debug_name),
+        local_decls(main_zone(), sig),
+        source_position_table_(this->graph()),
+        interpreter_(nullptr) {
+    // Create our own function.
+    function_ = new WasmFunction();
+    function_->sig = sig;
+    function_->func_index = 0;
+    function_->sig_index = 0;
+    if (mode == kExecuteInterpreted) {
+      interpreter_ = new WasmInterpreter(nullptr, zone()->allocator());
+      int index = interpreter_->AddFunctionForTesting(function_);
+      CHECK_EQ(0, index);
+    }
+  }
+
+  explicit WasmFunctionCompiler(
       FunctionSig* sig, TestingModule* module,
       Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
       : GraphAndBuilders(main_zone()),
+        execution_mode_(module->execution_mode()),
         jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
                 nullptr, this->machine()),
         sig(sig),
@@ -423,23 +463,20 @@
         testing_module_(module),
         debug_name_(debug_name),
         local_decls(main_zone(), sig),
-        source_position_table_(this->graph()) {
-    if (module) {
-      // Get a new function from the testing module.
-      function_ = nullptr;
-      function_index_ = module->AddFunction(sig, Handle<Code>::null());
-    } else {
-      // Create our own function.
-      function_ = new WasmFunction();
-      function_->sig = sig;
-      function_index_ = 0;
-    }
+        source_position_table_(this->graph()),
+        interpreter_(module->interpreter()) {
+    // Get a new function from the testing module.
+    int index = module->AddFunction(sig, Handle<Code>::null());
+    function_ = testing_module_->GetFunctionAt(index);
   }
 
   ~WasmFunctionCompiler() {
-    if (function_) delete function_;
+    if (testing_module_) return;  // testing module owns the below things.
+    delete function_;
+    if (interpreter_) delete interpreter_;
   }
 
+  WasmExecutionMode execution_mode_;
   JSGraph jsgraph;
   FunctionSig* sig;
   // The call descriptor is initialized when the function is compiled.
@@ -447,9 +484,9 @@
   TestingModule* testing_module_;
   Vector<const char> debug_name_;
   WasmFunction* function_;
-  int function_index_;
   LocalDeclEncoder local_decls;
   SourcePositionTable source_position_table_;
+  WasmInterpreter* interpreter_;
 
   Isolate* isolate() { return main_isolate(); }
   Graph* graph() const { return main_graph_; }
@@ -462,13 +499,17 @@
     }
   }
   CallDescriptor* descriptor() { return descriptor_; }
+  uint32_t function_index() { return function_->func_index; }
 
   void Build(const byte* start, const byte* end) {
     // Build the TurboFan graph.
-    local_decls.Prepend(&start, &end);
+    local_decls.Prepend(main_zone(), &start, &end);
     TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig,
                       &source_position_table_, start, end);
-    delete[] start;
+    if (interpreter_) {
+      // Add the code to the interpreter.
+      CHECK(interpreter_->SetFunctionCodeForTesting(function_, start, end));
+    }
   }
 
   byte AllocateLocal(LocalType type) {
@@ -494,13 +535,13 @@
 
     Handle<Code> code = info.code();
 
-    // Length is always 2, since usually <wasm_obj, func_index> is stored in the
-    // deopt data. Here, we only store the function index.
+    // Length is always 2, since usually <wasm_obj, func_index> is stored in
+    // the deopt data. Here, we only store the function index.
     DCHECK(code->deoptimization_data() == nullptr ||
            code->deoptimization_data()->length() == 0);
     Handle<FixedArray> deopt_data =
         isolate()->factory()->NewFixedArray(2, TENURED);
-    deopt_data->set(1, Smi::FromInt(function_index_));
+    deopt_data->set(1, Smi::FromInt(static_cast<int>(function_index())));
     deopt_data->set_length(2);
     code->set_deoptimization_data(*deopt_data);
 
@@ -516,15 +557,10 @@
 
   uint32_t CompileAndAdd(uint16_t sig_index = 0) {
     CHECK(testing_module_);
-    function()->sig_index = sig_index;
+    function_->sig_index = sig_index;
     Handle<Code> code = Compile();
-    testing_module_->SetFunctionCode(function_index_, code);
-    return static_cast<uint32_t>(function_index_);
-  }
-
-  WasmFunction* function() {
-    if (function_) return function_;
-    return &testing_module_->module->functions[function_index_];
+    testing_module_->SetFunctionCode(function_index(), code);
+    return function_index();
   }
 
   // Set the context, such that e.g. runtime functions can be called.
@@ -543,7 +579,8 @@
 template <typename ReturnType>
 class WasmRunner {
  public:
-  WasmRunner(MachineType p0 = MachineType::None(),
+  WasmRunner(WasmExecutionMode execution_mode,
+             MachineType p0 = MachineType::None(),
              MachineType p1 = MachineType::None(),
              MachineType p2 = MachineType::None(),
              MachineType p3 = MachineType::None())
@@ -551,7 +588,7 @@
         compiled_(false),
         signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
                    GetParameterCount(p0, p1, p2, p3), storage_),
-        compiler_(&signature_, nullptr) {
+        compiler_(&signature_, execution_mode) {
     InitSigStorage(p0, p1, p2, p3);
   }
 
@@ -594,51 +631,102 @@
   void Build(const byte* start, const byte* end) {
     CHECK(!compiled_);
     compiled_ = true;
-
-    // Build the TF graph within the compiler.
     compiler_.Build(start, end);
-    // Generate code.
-    Handle<Code> code = compiler_.Compile();
 
-    if (compiler_.testing_module_) {
-      // Update the table of function code in the module.
-      compiler_.testing_module_->SetFunctionCode(compiler_.function_index_,
-                                                 code);
+    if (!interpret()) {
+      // Compile machine code and install it into the module.
+      Handle<Code> code = compiler_.Compile();
+
+      if (compiler_.testing_module_) {
+        // Update the table of function code in the module.
+        compiler_.testing_module_->SetFunctionCode(
+            compiler_.function_->func_index, code);
+      }
+
+      wrapper_.SetInnerCode(code);
     }
-
-    wrapper_.SetInnerCode(code);
   }
 
-  ReturnType Call() { return Call(0, 0, 0, 0); }
+  ReturnType Call() {
+    if (interpret()) {
+      return CallInterpreter(Vector<WasmVal>(nullptr, 0));
+    } else {
+      return Call(0, 0, 0, 0);
+    }
+  }
 
   template <typename P0>
   ReturnType Call(P0 p0) {
-    return Call(p0, 0, 0, 0);
+    if (interpret()) {
+      WasmVal args[] = {WasmVal(p0)};
+      return CallInterpreter(ArrayVector(args));
+    } else {
+      return Call(p0, 0, 0, 0);
+    }
   }
 
   template <typename P0, typename P1>
   ReturnType Call(P0 p0, P1 p1) {
-    return Call(p0, p1, 0, 0);
+    if (interpret()) {
+      WasmVal args[] = {WasmVal(p0), WasmVal(p1)};
+      return CallInterpreter(ArrayVector(args));
+    } else {
+      return Call(p0, p1, 0, 0);
+    }
   }
 
   template <typename P0, typename P1, typename P2>
   ReturnType Call(P0 p0, P1 p1, P2 p2) {
-    return Call(p0, p1, p2, 0);
+    if (interpret()) {
+      WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2)};
+      return CallInterpreter(ArrayVector(args));
+    } else {
+      return Call(p0, p1, p2, 0);
+    }
   }
 
   template <typename P0, typename P1, typename P2, typename P3>
   ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
-    CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
-                               wrapper_.GetWrapperCode(), wrapper_.signature());
-    ReturnType return_value;
-    int32_t result = runner.Call<void*, void*, void*, void*, void*>(
-        &p0, &p1, &p2, &p3, &return_value);
-    CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
-    return return_value;
+    if (interpret()) {
+      WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2), WasmVal(p3)};
+      return CallInterpreter(ArrayVector(args));
+    } else {
+      CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
+                                 wrapper_.GetWrapperCode(),
+                                 wrapper_.signature());
+      ReturnType return_value;
+      int32_t result = runner.Call<void*, void*, void*, void*, void*>(
+          &p0, &p1, &p2, &p3, &return_value);
+      CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
+      return return_value;
+    }
+  }
+
+  ReturnType CallInterpreter(Vector<WasmVal> args) {
+    CHECK_EQ(args.length(),
+             static_cast<int>(compiler_.function_->sig->parameter_count()));
+    WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
+    thread->Reset();
+    thread->PushFrame(compiler_.function_, args.start());
+    if (thread->Run() == WasmInterpreter::FINISHED) {
+      WasmVal val = thread->GetReturnValue();
+      return val.to<ReturnType>();
+    } else if (thread->state() == WasmInterpreter::TRAPPED) {
+      // TODO(titzer): return the correct trap code
+      int64_t result = 0xdeadbeefdeadbeef;
+      return static_cast<ReturnType>(result);
+    } else {
+      // TODO(titzer): falling off end
+      ReturnType val = 0;
+      return val;
+    }
   }
 
   byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); }
 
+  WasmFunction* function() { return compiler_.function_; }
+  WasmInterpreter* interpreter() { return compiler_.interpreter_; }
+
  protected:
   v8::base::AccountingAllocator allocator_;
   Zone zone;
@@ -648,6 +736,8 @@
   WasmFunctionCompiler compiler_;
   WasmFunctionWrapper<ReturnType> wrapper_;
 
+  bool interpret() { return compiler_.execution_mode_ == kExecuteInterpreted; }
+
   static size_t GetParameterCount(MachineType p0, MachineType p1,
                                   MachineType p2, MachineType p3) {
     if (p0 == MachineType::None()) return 0;
@@ -662,10 +752,11 @@
 // Currently only supports compiled tests, but a future
 // RunWasmInterpreted_##name version will allow each test to also run in the
 // interpreter.
-#define WASM_EXEC_TEST(name)                         \
-  void RunWasm_##name();                             \
-  TEST(RunWasmCompiled_##name) { RunWasm_##name(); } \
-  void RunWasm_##name()
+#define WASM_EXEC_TEST(name)                                               \
+  void RunWasm_##name(WasmExecutionMode execution_mode);                   \
+  TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); }       \
+  TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \
+  void RunWasm_##name(WasmExecutionMode execution_mode)
 
 }  // namespace