Upgrade V8 to version 4.9.385.28

https://chromium.googlesource.com/v8/v8/+/4.9.385.28

FPIIM-449

Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h
new file mode 100644
index 0000000..cc23b46
--- /dev/null
+++ b/test/cctest/wasm/wasm-run-utils.h
@@ -0,0 +1,391 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WASM_RUN_UTILS_H
+#define WASM_RUN_UTILS_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "src/base/utils/random-number-generator.h"
+
+#include "src/compiler/graph-visualizer.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/wasm-compiler.h"
+
+#include "src/wasm/ast-decoder.h"
+#include "src/wasm/wasm-js.h"
+#include "src/wasm/wasm-module.h"
+#include "src/wasm/wasm-opcodes.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/codegen-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
+
+// 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
+// exception.
+#define CHECK_TRAP32(x) \
+  CHECK_EQ(0xdeadbeef, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF)
+#define CHECK_TRAP64(x) \
+  CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
+#define CHECK_TRAP(x) CHECK_TRAP32(x)
+
+namespace {
+using namespace v8::base;
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+using namespace v8::internal::wasm;
+
+inline void init_env(FunctionEnv* env, FunctionSig* sig) {
+  env->module = nullptr;
+  env->sig = sig;
+  env->local_int32_count = 0;
+  env->local_int64_count = 0;
+  env->local_float32_count = 0;
+  env->local_float64_count = 0;
+  env->SumLocals();
+}
+
+const uint32_t kMaxGlobalsSize = 128;
+
+// A helper for module environments that adds the ability to allocate memory
+// and global variables.
+class TestingModule : public ModuleEnv {
+ public:
+  TestingModule() : mem_size(0), global_offset(0) {
+    globals_area = 0;
+    mem_start = 0;
+    mem_end = 0;
+    module = nullptr;
+    linker = nullptr;
+    function_code = nullptr;
+    asm_js = false;
+    memset(global_data, 0, sizeof(global_data));
+  }
+
+  ~TestingModule() {
+    if (mem_start) {
+      free(raw_mem_start<byte>());
+    }
+    if (function_code) delete function_code;
+    if (module) delete module;
+  }
+
+  byte* AddMemory(size_t size) {
+    CHECK_EQ(0, mem_start);
+    CHECK_EQ(0, mem_size);
+    mem_start = reinterpret_cast<uintptr_t>(malloc(size));
+    CHECK(mem_start);
+    byte* raw = raw_mem_start<byte>();
+    memset(raw, 0, size);
+    mem_end = mem_start + size;
+    mem_size = size;
+    return raw_mem_start<byte>();
+  }
+
+  template <typename T>
+  T* AddMemoryElems(size_t count) {
+    AddMemory(count * sizeof(T));
+    return raw_mem_start<T>();
+  }
+
+  template <typename T>
+  T* AddGlobal(MachineType mem_type) {
+    WasmGlobal* global = AddGlobal(mem_type);
+    return reinterpret_cast<T*>(globals_area + global->offset);
+  }
+
+  byte AddSignature(FunctionSig* sig) {
+    AllocModule();
+    if (!module->signatures) {
+      module->signatures = new std::vector<FunctionSig*>();
+    }
+    module->signatures->push_back(sig);
+    size_t size = module->signatures->size();
+    CHECK(size < 127);
+    return static_cast<byte>(size - 1);
+  }
+
+  template <typename T>
+  T* raw_mem_start() {
+    DCHECK(mem_start);
+    return reinterpret_cast<T*>(mem_start);
+  }
+
+  template <typename T>
+  T* raw_mem_end() {
+    DCHECK(mem_end);
+    return reinterpret_cast<T*>(mem_end);
+  }
+
+  template <typename T>
+  T raw_mem_at(int i) {
+    DCHECK(mem_start);
+    return reinterpret_cast<T*>(mem_start)[i];
+  }
+
+  template <typename T>
+  T raw_val_at(int i) {
+    T val;
+    memcpy(&val, reinterpret_cast<void*>(mem_start + i), sizeof(T));
+    return val;
+  }
+
+  // Zero-initialize the memory.
+  void BlankMemory() {
+    byte* raw = raw_mem_start<byte>();
+    memset(raw, 0, mem_size);
+  }
+
+  // Pseudo-randomly intialize the memory.
+  void RandomizeMemory(unsigned int seed = 88) {
+    byte* raw = raw_mem_start<byte>();
+    byte* end = raw_mem_end<byte>();
+    v8::base::RandomNumberGenerator rng;
+    rng.SetSeed(seed);
+    rng.NextBytes(raw, end - raw);
+  }
+
+  WasmFunction* AddFunction(FunctionSig* sig, Handle<Code> code) {
+    AllocModule();
+    if (module->functions == nullptr) {
+      module->functions = new std::vector<WasmFunction>();
+      function_code = new std::vector<Handle<Code>>();
+    }
+    module->functions->push_back({sig, 0, 0, 0, 0, 0, 0, 0, false, false});
+    function_code->push_back(code);
+    return &module->functions->back();
+  }
+
+ private:
+  size_t mem_size;
+  uint32_t global_offset;
+  byte global_data[kMaxGlobalsSize];
+
+  WasmGlobal* AddGlobal(MachineType mem_type) {
+    AllocModule();
+    if (globals_area == 0) {
+      globals_area = reinterpret_cast<uintptr_t>(global_data);
+      module->globals = new std::vector<WasmGlobal>();
+    }
+    byte size = WasmOpcodes::MemSize(mem_type);
+    global_offset = (global_offset + size - 1) & ~(size - 1);  // align
+    module->globals->push_back({0, mem_type, global_offset, false});
+    global_offset += size;
+    // limit number of globals.
+    CHECK_LT(global_offset, kMaxGlobalsSize);
+    return &module->globals->back();
+  }
+  void AllocModule() {
+    if (module == nullptr) {
+      module = new WasmModule();
+      module->shared_isolate = CcTest::InitIsolateOnce();
+      module->globals = nullptr;
+      module->functions = nullptr;
+      module->data_segments = nullptr;
+    }
+  }
+};
+
+
+inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, FunctionEnv* env,
+                              const byte* start, const byte* end) {
+  compiler::WasmGraphBuilder builder(zone, jsgraph, env->sig);
+  TreeResult result = BuildTFGraph(&builder, env, start, end);
+  if (result.failed()) {
+    ptrdiff_t pc = result.error_pc - result.start;
+    ptrdiff_t pt = result.error_pt - result.start;
+    std::ostringstream str;
+    str << "Verification failed: " << result.error_code << " pc = +" << pc;
+    if (result.error_pt) str << ", pt = +" << pt;
+    str << ", msg = " << result.error_msg.get();
+    FATAL(str.str().c_str());
+  }
+  if (FLAG_trace_turbo_graph) {
+    OFStream os(stdout);
+    os << AsRPO(*jsgraph->graph());
+  }
+}
+
+
+// A helper for compiling functions that are only internally callable WASM code.
+class WasmFunctionCompiler : public HandleAndZoneScope,
+                             private GraphAndBuilders {
+ public:
+  explicit WasmFunctionCompiler(FunctionSig* sig, ModuleEnv* module = nullptr)
+      : GraphAndBuilders(main_zone()),
+        jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
+                nullptr, this->machine()),
+        descriptor_(nullptr) {
+    init_env(&env, sig);
+    env.module = module;
+  }
+
+  JSGraph jsgraph;
+  FunctionEnv env;
+  // The call descriptor is initialized when the function is compiled.
+  CallDescriptor* descriptor_;
+
+  Isolate* isolate() { return main_isolate(); }
+  Graph* graph() const { return main_graph_; }
+  Zone* zone() const { return graph()->zone(); }
+  CommonOperatorBuilder* common() { return &main_common_; }
+  MachineOperatorBuilder* machine() { return &main_machine_; }
+  CallDescriptor* descriptor() { return descriptor_; }
+
+  void Build(const byte* start, const byte* end) {
+    TestBuildingGraph(main_zone(), &jsgraph, &env, start, end);
+  }
+
+  byte AllocateLocal(LocalType type) {
+    int result = static_cast<int>(env.total_locals);
+    env.AddLocals(type, 1);
+    byte b = static_cast<byte>(result);
+    CHECK_EQ(result, b);
+    return b;
+  }
+
+  Handle<Code> Compile(ModuleEnv* module) {
+    descriptor_ = module->GetWasmCallDescriptor(this->zone(), env.sig);
+    CompilationInfo info("wasm compile", this->isolate(), this->zone());
+    Handle<Code> result =
+        Pipeline::GenerateCodeForTesting(&info, descriptor_, this->graph());
+#ifdef ENABLE_DISASSEMBLER
+    if (!result.is_null() && FLAG_print_opt_code) {
+      OFStream os(stdout);
+      result->Disassemble("wasm code", os);
+    }
+#endif
+
+    return result;
+  }
+
+  uint32_t CompileAndAdd(TestingModule* module) {
+    uint32_t index = 0;
+    if (module->module && module->module->functions) {
+      index = static_cast<uint32_t>(module->module->functions->size());
+    }
+    module->AddFunction(env.sig, Compile(module));
+    return index;
+  }
+};
+
+
+// A helper class to build graphs from Wasm bytecode, generate machine
+// code, and run that code.
+template <typename ReturnType>
+class WasmRunner {
+ public:
+  WasmRunner(MachineType p0 = MachineType::None(),
+             MachineType p1 = MachineType::None(),
+             MachineType p2 = MachineType::None(),
+             MachineType p3 = MachineType::None())
+      : signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
+                   GetParameterCount(p0, p1, p2, p3), storage_),
+        compiler_(&signature_),
+        call_wrapper_(p0, p1, p2, p3),
+        compilation_done_(false) {
+    int index = 0;
+    MachineType ret = MachineTypeForC<ReturnType>();
+    if (ret != MachineType::None()) {
+      storage_[index++] = WasmOpcodes::LocalTypeFor(ret);
+    }
+    if (p0 != MachineType::None())
+      storage_[index++] = WasmOpcodes::LocalTypeFor(p0);
+    if (p1 != MachineType::None())
+      storage_[index++] = WasmOpcodes::LocalTypeFor(p1);
+    if (p2 != MachineType::None())
+      storage_[index++] = WasmOpcodes::LocalTypeFor(p2);
+    if (p3 != MachineType::None())
+      storage_[index++] = WasmOpcodes::LocalTypeFor(p3);
+  }
+
+
+  FunctionEnv* env() { return &compiler_.env; }
+
+
+  // Builds a graph from the given Wasm code, and generates the machine
+  // code and call wrapper for that graph. This method must not be called
+  // more than once.
+  void Build(const byte* start, const byte* end) {
+    DCHECK(!compilation_done_);
+    compilation_done_ = true;
+    // Build the TF graph.
+    compiler_.Build(start, end);
+    // Generate code.
+    Handle<Code> code = compiler_.Compile(env()->module);
+
+    // Construct the call wrapper.
+    Node* inputs[5];
+    int input_count = 0;
+    inputs[input_count++] = call_wrapper_.HeapConstant(code);
+    for (size_t i = 0; i < signature_.parameter_count(); i++) {
+      inputs[input_count++] = call_wrapper_.Parameter(i);
+    }
+
+    call_wrapper_.Return(call_wrapper_.AddNode(
+        call_wrapper_.common()->Call(compiler_.descriptor()), input_count,
+        inputs));
+  }
+
+  ReturnType Call() { return call_wrapper_.Call(); }
+
+  template <typename P0>
+  ReturnType Call(P0 p0) {
+    return call_wrapper_.Call(p0);
+  }
+
+  template <typename P0, typename P1>
+  ReturnType Call(P0 p0, P1 p1) {
+    return call_wrapper_.Call(p0, p1);
+  }
+
+  template <typename P0, typename P1, typename P2>
+  ReturnType Call(P0 p0, P1 p1, P2 p2) {
+    return call_wrapper_.Call(p0, p1, p2);
+  }
+
+  template <typename P0, typename P1, typename P2, typename P3>
+  ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
+    return call_wrapper_.Call(p0, p1, p2, p3);
+  }
+
+  byte AllocateLocal(LocalType type) {
+    int result = static_cast<int>(env()->total_locals);
+    env()->AddLocals(type, 1);
+    byte b = static_cast<byte>(result);
+    CHECK_EQ(result, b);
+    return b;
+  }
+
+ private:
+  LocalType storage_[5];
+  FunctionSig signature_;
+  WasmFunctionCompiler compiler_;
+  BufferedRawMachineAssemblerTester<ReturnType> call_wrapper_;
+  bool compilation_done_;
+
+  static size_t GetParameterCount(MachineType p0, MachineType p1,
+                                  MachineType p2, MachineType p3) {
+    if (p0 == MachineType::None()) return 0;
+    if (p1 == MachineType::None()) return 1;
+    if (p2 == MachineType::None()) return 2;
+    if (p3 == MachineType::None()) return 3;
+    return 4;
+  }
+};
+
+}  // namespace
+
+#endif