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/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
index 17065d6..9c3858d 100644
--- a/src/compiler/wasm-compiler.cc
+++ b/src/compiler/wasm-compiler.cc
@@ -15,6 +15,7 @@
 #include "src/compiler/graph.h"
 #include "src/compiler/graph-visualizer.h"
 #include "src/compiler/instruction-selector.h"
+#include "src/compiler/int64-lowering.h"
 #include "src/compiler/js-generic-lowering.h"
 #include "src/compiler/js-graph.h"
 #include "src/compiler/js-operator.h"
@@ -29,6 +30,9 @@
 
 #include "src/code-factory.h"
 #include "src/code-stubs.h"
+#include "src/factory.h"
+#include "src/log-inl.h"
+#include "src/profiler/cpu-profiler.h"
 
 #include "src/wasm/ast-decoder.h"
 #include "src/wasm/wasm-module.h"
@@ -105,6 +109,9 @@
   // Make the current control path trap to unreachable.
   void Unreachable() { ConnectTrap(kTrapUnreachable); }
 
+  // Always trap with the given reason.
+  void TrapAlways(TrapReason reason) { ConnectTrap(reason); }
+
   // Add a check that traps if {node} is equal to {val}.
   Node* TrapIfEq32(TrapReason reason, Node* node, int32_t val) {
     Int32Matcher m(node);
@@ -165,6 +172,28 @@
     *effect_ptr = before;
   }
 
+  Node* GetTrapValue(wasm::FunctionSig* sig) {
+    if (sig->return_count() > 0) {
+      switch (sig->GetReturn()) {
+        case wasm::kAstI32:
+          return jsgraph()->Int32Constant(0xdeadbeef);
+        case wasm::kAstI64:
+          return jsgraph()->Int64Constant(0xdeadbeefdeadbeef);
+        case wasm::kAstF32:
+          return jsgraph()->Float32Constant(bit_cast<float>(0xdeadbeef));
+        case wasm::kAstF64:
+          return jsgraph()->Float64Constant(
+              bit_cast<double>(0xdeadbeefdeadbeef));
+          break;
+        default:
+          UNREACHABLE();
+          return nullptr;
+      }
+    } else {
+      return jsgraph()->Int32Constant(0xdeadbeef);
+    }
+  }
+
  private:
   WasmGraphBuilder* builder_;
   JSGraph* jsgraph_;
@@ -197,7 +226,7 @@
     *effect_ptr = effects_[reason] =
         graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr);
 
-    if (module && !module->context.is_null()) {
+    if (module && !module->instance->context.is_null()) {
       // Use the module context to call the runtime to throw an exception.
       Runtime::FunctionId f = Runtime::kThrow;
       const Runtime::Function* fun = Runtime::FunctionForId(f);
@@ -210,7 +239,7 @@
           jsgraph()->ExternalConstant(
               ExternalReference(f, jsgraph()->isolate())),  // ref
           jsgraph()->Int32Constant(fun->nargs),             // arity
-          jsgraph()->Constant(module->context),             // context
+          jsgraph()->Constant(module->instance->context),   // context
           *effect_ptr,
           *control_ptr};
 
@@ -227,29 +256,7 @@
       end = thrw;
     } else {
       // End the control flow with returning 0xdeadbeef
-      Node* ret_value;
-      if (builder_->GetFunctionSignature()->return_count() > 0) {
-        switch (builder_->GetFunctionSignature()->GetReturn()) {
-          case wasm::kAstI32:
-            ret_value = jsgraph()->Int32Constant(0xdeadbeef);
-            break;
-          case wasm::kAstI64:
-            ret_value = jsgraph()->Int64Constant(0xdeadbeefdeadbeef);
-            break;
-          case wasm::kAstF32:
-            ret_value = jsgraph()->Float32Constant(bit_cast<float>(0xdeadbeef));
-            break;
-          case wasm::kAstF64:
-            ret_value = jsgraph()->Float64Constant(
-                bit_cast<double>(0xdeadbeefdeadbeef));
-            break;
-          default:
-            UNREACHABLE();
-            ret_value = nullptr;
-        }
-      } else {
-        ret_value = jsgraph()->Int32Constant(0xdeadbeef);
-      }
+      Node* ret_value = GetTrapValue(builder_->GetFunctionSignature());
       end = graph()->NewNode(jsgraph()->common()->Return(), ret_value,
                              *effect_ptr, *control_ptr);
     }
@@ -475,6 +482,9 @@
       op = m->Uint32LessThanOrEqual();
       std::swap(left, right);
       break;
+    case wasm::kExprI64And:
+      op = m->Word64And();
+      break;
 #if WASM_64
     // Opcodes only supported on 64-bit platforms.
     // TODO(titzer): query the machine operator builder here instead of #ifdef.
@@ -525,9 +535,6 @@
       op = m->Uint64Mod();
       return graph()->NewNode(op, left, right,
                               trap_->ZeroCheck64(kTrapRemByZero, right));
-    case wasm::kExprI64And:
-      op = m->Word64And();
-      break;
     case wasm::kExprI64Ior:
       op = m->Word64Or();
       break;
@@ -696,14 +703,10 @@
       op = m->ChangeUint32ToFloat64();
       break;
     case wasm::kExprF32SConvertI32:
-      op = m->ChangeInt32ToFloat64();  // TODO(titzer): two conversions
-      input = graph()->NewNode(op, input);
-      op = m->TruncateFloat64ToFloat32();
+      op = m->RoundInt32ToFloat32();
       break;
     case wasm::kExprF32UConvertI32:
-      op = m->ChangeUint32ToFloat64();
-      input = graph()->NewNode(op, input);
-      op = m->TruncateFloat64ToFloat32();
+      op = m->RoundUint32ToFloat32();
       break;
     case wasm::kExprI32SConvertF32:
       return BuildI32SConvertF32(input);
@@ -725,6 +728,10 @@
       if (m->Word32Ctz().IsSupported()) {
         op = m->Word32Ctz().op();
         break;
+      } else if (m->Word32ReverseBits().IsSupported()) {
+        Node* reversed = graph()->NewNode(m->Word32ReverseBits().op(), input);
+        Node* result = graph()->NewNode(m->Word32Clz(), reversed);
+        return result;
       } else {
         return BuildI32Ctz(input);
       }
@@ -738,84 +745,53 @@
       }
     }
     case wasm::kExprF32Floor: {
-      if (m->Float32RoundDown().IsSupported()) {
-        op = m->Float32RoundDown().op();
-        break;
-      } else {
-        op = UnsupportedOpcode(opcode);
-        break;
-      }
+      if (!m->Float32RoundDown().IsSupported()) return BuildF32Floor(input);
+      op = m->Float32RoundDown().op();
+      break;
     }
     case wasm::kExprF32Ceil: {
-      if (m->Float32RoundUp().IsSupported()) {
-        op = m->Float32RoundUp().op();
-        break;
-      } else {
-        op = UnsupportedOpcode(opcode);
-        break;
-      }
+      if (!m->Float32RoundUp().IsSupported()) return BuildF32Ceil(input);
+      op = m->Float32RoundUp().op();
+      break;
     }
     case wasm::kExprF32Trunc: {
-      if (m->Float32RoundTruncate().IsSupported()) {
-        op = m->Float32RoundTruncate().op();
-        break;
-      } else {
-        op = UnsupportedOpcode(opcode);
-        break;
-      }
+      if (!m->Float32RoundTruncate().IsSupported()) return BuildF32Trunc(input);
+      op = m->Float32RoundTruncate().op();
+      break;
     }
     case wasm::kExprF32NearestInt: {
-      if (m->Float32RoundTiesEven().IsSupported()) {
-        op = m->Float32RoundTiesEven().op();
-        break;
-      } else {
-        op = UnsupportedOpcode(opcode);
-        break;
-      }
+      if (!m->Float32RoundTiesEven().IsSupported())
+        return BuildF32NearestInt(input);
+      op = m->Float32RoundTiesEven().op();
+      break;
     }
     case wasm::kExprF64Floor: {
-      if (m->Float64RoundDown().IsSupported()) {
-        op = m->Float64RoundDown().op();
-        break;
-      } else {
-        op = UnsupportedOpcode(opcode);
-        break;
-      }
+      if (!m->Float64RoundDown().IsSupported()) return BuildF64Floor(input);
+      op = m->Float64RoundDown().op();
+      break;
     }
     case wasm::kExprF64Ceil: {
-      if (m->Float64RoundUp().IsSupported()) {
-        op = m->Float64RoundUp().op();
-        break;
-      } else {
-        op = UnsupportedOpcode(opcode);
-        break;
-      }
+      if (!m->Float64RoundUp().IsSupported()) return BuildF64Ceil(input);
+      op = m->Float64RoundUp().op();
+      break;
     }
     case wasm::kExprF64Trunc: {
-      if (m->Float64RoundTruncate().IsSupported()) {
-        op = m->Float64RoundTruncate().op();
-        break;
-      } else {
-        op = UnsupportedOpcode(opcode);
-        break;
-      }
+      if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input);
+      op = m->Float64RoundTruncate().op();
+      break;
     }
     case wasm::kExprF64NearestInt: {
-      if (m->Float64RoundTiesEven().IsSupported()) {
-        op = m->Float64RoundTiesEven().op();
-        break;
-      } else {
-        op = UnsupportedOpcode(opcode);
-        break;
-      }
+      if (!m->Float64RoundTiesEven().IsSupported())
+        return BuildF64NearestInt(input);
+      op = m->Float64RoundTiesEven().op();
+      break;
     }
-
-#if WASM_64
-    // Opcodes only supported on 64-bit platforms.
-    // TODO(titzer): query the machine operator builder here instead of #ifdef.
     case wasm::kExprI32ConvertI64:
       op = m->TruncateInt64ToInt32();
       break;
+#if WASM_64
+    // Opcodes only supported on 64-bit platforms.
+    // TODO(titzer): query the machine operator builder here instead of #ifdef.
     case wasm::kExprI64SConvertI32:
       op = m->ChangeInt32ToInt64();
       break;
@@ -883,6 +859,10 @@
       if (m->Word64Ctz().IsSupported()) {
         op = m->Word64Ctz().op();
         break;
+      } else if (m->Word64ReverseBits().IsSupported()) {
+        Node* reversed = graph()->NewNode(m->Word64ReverseBits().op(), input);
+        Node* result = graph()->NewNode(m->Word64Clz(), reversed);
+        return result;
       } else {
         return BuildI64Ctz(input);
       }
@@ -1061,8 +1041,12 @@
 
   return left_le_right.Phi(
       wasm::kAstF32, left,
-      right_lt_left.Phi(wasm::kAstF32, right,
-                        left_is_not_nan.Phi(wasm::kAstF32, right, left)));
+      right_lt_left.Phi(
+          wasm::kAstF32, right,
+          left_is_not_nan.Phi(
+              wasm::kAstF32,
+              Binop(wasm::kExprF32Mul, right, Float32Constant(1.0)),
+              Binop(wasm::kExprF32Mul, left, Float32Constant(1.0)))));
 }
 
 
@@ -1078,8 +1062,12 @@
 
   return left_ge_right.Phi(
       wasm::kAstF32, left,
-      right_gt_left.Phi(wasm::kAstF32, right,
-                        left_is_not_nan.Phi(wasm::kAstF32, right, left)));
+      right_gt_left.Phi(
+          wasm::kAstF32, right,
+          left_is_not_nan.Phi(
+              wasm::kAstF32,
+              Binop(wasm::kExprF32Mul, right, Float32Constant(1.0)),
+              Binop(wasm::kExprF32Mul, left, Float32Constant(1.0)))));
 }
 
 
@@ -1095,8 +1083,12 @@
 
   return left_le_right.Phi(
       wasm::kAstF64, left,
-      right_lt_left.Phi(wasm::kAstF64, right,
-                        left_is_not_nan.Phi(wasm::kAstF64, right, left)));
+      right_lt_left.Phi(
+          wasm::kAstF64, right,
+          left_is_not_nan.Phi(
+              wasm::kAstF64,
+              Binop(wasm::kExprF64Mul, right, Float64Constant(1.0)),
+              Binop(wasm::kExprF64Mul, left, Float64Constant(1.0)))));
 }
 
 
@@ -1112,8 +1104,12 @@
 
   return left_ge_right.Phi(
       wasm::kAstF64, left,
-      right_gt_left.Phi(wasm::kAstF64, right,
-                        left_is_not_nan.Phi(wasm::kAstF64, right, left)));
+      right_gt_left.Phi(
+          wasm::kAstF64, right,
+          left_is_not_nan.Phi(
+              wasm::kAstF64,
+              Binop(wasm::kExprF64Mul, right, Float64Constant(1.0)),
+              Binop(wasm::kExprF64Mul, left, Float64Constant(1.0)))));
 }
 
 
@@ -1121,14 +1117,12 @@
   MachineOperatorBuilder* m = jsgraph()->machine();
   // Truncation of the input value is needed for the overflow check later.
   Node* trunc = Unop(wasm::kExprF32Trunc, input);
-  // TODO(titzer): two conversions
-  Node* f64_trunc = graph()->NewNode(m->ChangeFloat32ToFloat64(), trunc);
-  Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), f64_trunc);
+  Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc);
 
   // Convert the result back to f64. If we end up at a different value than the
   // truncated input value, then there has been an overflow and we trap.
-  Node* check = Unop(wasm::kExprF64SConvertI32, result);
-  Node* overflow = Binop(wasm::kExprF64Ne, f64_trunc, check);
+  Node* check = Unop(wasm::kExprF32SConvertI32, result);
+  Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
   trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow);
 
   return result;
@@ -1137,6 +1131,10 @@
 
 Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) {
   MachineOperatorBuilder* m = jsgraph()->machine();
+  if (module_ && module_->asm_js) {
+    return graph()->NewNode(
+        m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
+  }
   // Truncation of the input value is needed for the overflow check later.
   Node* trunc = Unop(wasm::kExprF64Trunc, input);
   Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc);
@@ -1155,14 +1153,12 @@
   MachineOperatorBuilder* m = jsgraph()->machine();
   // Truncation of the input value is needed for the overflow check later.
   Node* trunc = Unop(wasm::kExprF32Trunc, input);
-  // TODO(titzer): two conversions
-  Node* f64_trunc = graph()->NewNode(m->ChangeFloat32ToFloat64(), trunc);
-  Node* result = graph()->NewNode(m->ChangeFloat64ToUint32(), f64_trunc);
+  Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc);
 
-  // Convert the result back to f64. If we end up at a different value than the
+  // Convert the result back to f32. If we end up at a different value than the
   // truncated input value, then there has been an overflow and we trap.
-  Node* check = Unop(wasm::kExprF64UConvertI32, result);
-  Node* overflow = Binop(wasm::kExprF64Ne, f64_trunc, check);
+  Node* check = Unop(wasm::kExprF32UConvertI32, result);
+  Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
   trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow);
 
   return result;
@@ -1171,6 +1167,10 @@
 
 Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) {
   MachineOperatorBuilder* m = jsgraph()->machine();
+  if (module_ && module_->asm_js) {
+    return graph()->NewNode(
+        m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
+  }
   // Truncation of the input value is needed for the overflow check later.
   Node* trunc = Unop(wasm::kExprF64Trunc, input);
   Node* result = graph()->NewNode(m->ChangeFloat64ToUint32(), trunc);
@@ -1360,6 +1360,117 @@
   return result;
 }
 
+Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
+  MachineType type = MachineType::Float32();
+  ExternalReference ref =
+      ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate());
+  return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
+  MachineType type = MachineType::Float32();
+  ExternalReference ref =
+      ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate());
+  return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
+  MachineType type = MachineType::Float32();
+  ExternalReference ref =
+      ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate());
+  return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
+  MachineType type = MachineType::Float32();
+  ExternalReference ref =
+      ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate());
+  return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
+  MachineType type = MachineType::Float64();
+  ExternalReference ref =
+      ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate());
+  return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
+  MachineType type = MachineType::Float64();
+  ExternalReference ref =
+      ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate());
+  return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
+  MachineType type = MachineType::Float64();
+  ExternalReference ref =
+      ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate());
+  return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
+  MachineType type = MachineType::Float64();
+  ExternalReference ref =
+      ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate());
+  return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildRoundingInstruction(Node* input,
+                                                 ExternalReference ref,
+                                                 MachineType type) {
+  // We do truncation by calling a C function which calculates the truncation
+  // for us. The input is passed to the C function as a double* to avoid double
+  // parameters. For this we reserve a slot on the stack, store the parameter in
+  // that slot, pass a pointer to the slot to the C function, and after calling
+  // the C function we collect the return value from the stack slot.
+
+  Node* stack_slot_param =
+      graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation()));
+
+  const Operator* store_op = jsgraph()->machine()->Store(
+      StoreRepresentation(type.representation(), kNoWriteBarrier));
+  *effect_ =
+      graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
+                       input, *effect_, *control_);
+
+  Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1);
+  sig_builder.AddParam(MachineType::Pointer());
+  Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
+
+  Node* args[] = {function, stack_slot_param};
+
+  BuildCCall(sig_builder.Build(), args);
+
+  const Operator* load_op = jsgraph()->machine()->Load(type);
+
+  Node* load =
+      graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0),
+                       *effect_, *control_);
+  *effect_ = load;
+  return load;
+}
+
+Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) {
+  const size_t params = sig->parameter_count();
+  const size_t extra = 2;  // effect and control inputs.
+  const size_t count = 1 + params + extra;
+
+  // Reallocate the buffer to make space for extra inputs.
+  args = Realloc(args, count);
+
+  // Add effect and control inputs.
+  args[params + 1] = *effect_;
+  args[params + 2] = *control_;
+
+  CallDescriptor* desc =
+      Linkage::GetSimplifiedCDescriptor(jsgraph()->zone(), sig);
+
+  const Operator* op = jsgraph()->common()->Call(desc);
+  Node* call = graph()->NewNode(op, static_cast<int>(count), args);
+  *effect_ = call;
+  return call;
+}
 
 Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) {
   const size_t params = sig->parameter_count();
@@ -1373,8 +1484,9 @@
   args[params + 1] = *effect_;
   args[params + 2] = *control_;
 
-  const Operator* op = jsgraph()->common()->Call(
-      module_->GetWasmCallDescriptor(jsgraph()->zone(), sig));
+  CallDescriptor* descriptor =
+      wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig);
+  const Operator* op = jsgraph()->common()->Call(descriptor);
   Node* call = graph()->NewNode(op, static_cast<int>(count), args);
 
   *effect_ = call;
@@ -1392,23 +1504,38 @@
   return BuildWasmCall(sig, args);
 }
 
+Node* WasmGraphBuilder::CallImport(uint32_t index, Node** args) {
+  DCHECK_NULL(args[0]);
+
+  // Add code object as constant.
+  args[0] = Constant(module_->GetImportCode(index));
+  wasm::FunctionSig* sig = module_->GetImportSignature(index);
+
+  return BuildWasmCall(sig, args);
+}
 
 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args) {
   DCHECK_NOT_NULL(args[0]);
+  DCHECK(module_ && module_->instance);
 
   MachineOperatorBuilder* machine = jsgraph()->machine();
 
   // Compute the code object by loading it from the function table.
   Node* key = args[0];
-  Node* table = FunctionTable();
 
   // Bounds check the index.
   int table_size = static_cast<int>(module_->FunctionTableSize());
-  {
+  if (table_size > 0) {
+    // Bounds check against the table size.
     Node* size = Int32Constant(static_cast<int>(table_size));
     Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size);
     trap_->AddTrapIfFalse(kTrapFuncInvalid, in_bounds);
+  } else {
+    // No function table. Generate a trap and return a constant.
+    trap_->AddTrapIfFalse(kTrapFuncInvalid, Int32Constant(0));
+    return trap_->GetTrapValue(module_->GetSignature(index));
   }
+  Node* table = FunctionTable();
 
   // Load signature from the table and check.
   // The table is a FixedArray; signatures are encoded as SMIs.
@@ -1546,7 +1673,8 @@
   args[pos++] = *control_;
 
   // Call the WASM code.
-  CallDescriptor* desc = module_->GetWasmCallDescriptor(jsgraph()->zone(), sig);
+  CallDescriptor* desc =
+      wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig);
   Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args);
   Node* jsval =
       ToJS(call, context,
@@ -1631,18 +1759,23 @@
 
 
 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
+  DCHECK(module_ && module_->instance);
   if (offset == 0) {
-    if (!mem_buffer_)
-      mem_buffer_ = jsgraph()->IntPtrConstant(module_->mem_start);
+    if (!mem_buffer_) {
+      mem_buffer_ = jsgraph()->IntPtrConstant(
+          reinterpret_cast<uintptr_t>(module_->instance->mem_start));
+    }
     return mem_buffer_;
   } else {
-    return jsgraph()->IntPtrConstant(module_->mem_start + offset);
+    return jsgraph()->IntPtrConstant(
+        reinterpret_cast<uintptr_t>(module_->instance->mem_start + offset));
   }
 }
 
 
 Node* WasmGraphBuilder::MemSize(uint32_t offset) {
-  int32_t size = static_cast<int>(module_->mem_end - module_->mem_start);
+  DCHECK(module_ && module_->instance);
+  uint32_t size = static_cast<uint32_t>(module_->instance->mem_size);
   if (offset == 0) {
     if (!mem_size_) mem_size_ = jsgraph()->Int32Constant(size);
     return mem_size_;
@@ -1653,18 +1786,21 @@
 
 
 Node* WasmGraphBuilder::FunctionTable() {
+  DCHECK(module_ && module_->instance &&
+         !module_->instance->function_table.is_null());
   if (!function_table_) {
-    DCHECK(!module_->function_table.is_null());
-    function_table_ = jsgraph()->Constant(module_->function_table);
+    function_table_ = jsgraph()->Constant(module_->instance->function_table);
   }
   return function_table_;
 }
 
 
 Node* WasmGraphBuilder::LoadGlobal(uint32_t index) {
+  DCHECK(module_ && module_->instance && module_->instance->globals_start);
   MachineType mem_type = module_->GetGlobalType(index);
   Node* addr = jsgraph()->IntPtrConstant(
-      module_->globals_area + module_->module->globals->at(index).offset);
+      reinterpret_cast<uintptr_t>(module_->instance->globals_start +
+                                  module_->module->globals->at(index).offset));
   const Operator* op = jsgraph()->machine()->Load(mem_type);
   Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), *effect_,
                                 *control_);
@@ -1674,9 +1810,11 @@
 
 
 Node* WasmGraphBuilder::StoreGlobal(uint32_t index, Node* val) {
+  DCHECK(module_ && module_->instance && module_->instance->globals_start);
   MachineType mem_type = module_->GetGlobalType(index);
   Node* addr = jsgraph()->IntPtrConstant(
-      module_->globals_area + module_->module->globals->at(index).offset);
+      reinterpret_cast<uintptr_t>(module_->instance->globals_start +
+                                  module_->module->globals->at(index).offset));
   const Operator* op = jsgraph()->machine()->Store(
       StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
   Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val,
@@ -1689,12 +1827,11 @@
 void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index,
                                       uint32_t offset) {
   // TODO(turbofan): fold bounds checks for constant indexes.
-  CHECK_GE(module_->mem_end, module_->mem_start);
-  ptrdiff_t size = module_->mem_end - module_->mem_start;
+  DCHECK(module_ && module_->instance);
+  size_t size = module_->instance->mem_size;
   byte memsize = wasm::WasmOpcodes::MemSize(memtype);
   Node* cond;
-  if (static_cast<ptrdiff_t>(offset) >= size ||
-      static_cast<ptrdiff_t>(offset + memsize) > size) {
+  if (offset >= size || (static_cast<uint64_t>(offset) + memsize) > size) {
     // The access will always throw.
     cond = jsgraph()->Int32Constant(0);
   } else {
@@ -1782,6 +1919,35 @@
 
 Graph* WasmGraphBuilder::graph() { return jsgraph()->graph(); }
 
+void WasmGraphBuilder::Int64LoweringForTesting() {
+  if (kPointerSize == 4) {
+    Int64Lowering r(jsgraph()->graph(), jsgraph()->machine(),
+                    jsgraph()->common(), jsgraph()->zone(),
+                    function_signature_);
+    r.LowerGraph();
+  }
+}
+
+static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
+                                      CompilationInfo* info,
+                                      const char* message, uint32_t index,
+                                      const char* func_name) {
+  Isolate* isolate = info->isolate();
+  if (isolate->logger()->is_logging_code_events() ||
+      isolate->cpu_profiler()->is_profiling()) {
+    ScopedVector<char> buffer(128);
+    SNPrintF(buffer, "%s#%d:%s", message, index, func_name);
+    Handle<String> name_str =
+        isolate->factory()->NewStringFromAsciiChecked(buffer.start());
+    Handle<String> script_str =
+        isolate->factory()->NewStringFromAsciiChecked("(WASM)");
+    Handle<Code> code = info->code();
+    Handle<SharedFunctionInfo> shared =
+        isolate->factory()->NewSharedFunctionInfo(name_str, code, false);
+    PROFILE(isolate,
+            CodeCreateEvent(tag, *code, *shared, info, *script_str, 0, 0));
+  }
+}
 
 Handle<JSFunction> CompileJSToWasmWrapper(
     Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name,
@@ -1849,38 +2015,42 @@
         module->GetFunctionSignature(index)->parameter_count());
     CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
         &zone, false, params + 1, CallDescriptor::kNoFlags);
-    CompilationInfo info("js-to-wasm", isolate, &zone);
     // TODO(titzer): this is technically a WASM wrapper, not a wasm function.
-    info.set_output_code_kind(Code::WASM_FUNCTION);
+    Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION);
+    bool debugging =
+#if DEBUG
+        true;
+#else
+        FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
+#endif
+    const char* func_name = "js-to-wasm";
+
+    static unsigned id = 0;
+    Vector<char> buffer;
+    if (debugging) {
+      buffer = Vector<char>::New(128);
+      SNPrintF(buffer, "js-to-wasm#%d", id);
+      func_name = buffer.start();
+    }
+
+    CompilationInfo info(func_name, isolate, &zone, flags);
     Handle<Code> code =
         Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
-
-#ifdef ENABLE_DISASSEMBLER
-    // Disassemble the wrapper code for debugging.
-    if (!code.is_null() && FLAG_print_opt_code) {
-      Vector<char> buffer;
-      const char* name = "";
-      if (func->name_offset > 0) {
-        const byte* ptr = module->module->module_start + func->name_offset;
-        name = reinterpret_cast<const char*>(ptr);
-      }
-      SNPrintF(buffer, "JS->WASM function wrapper #%d:%s", index, name);
-      OFStream os(stdout);
-      code->Disassemble(buffer.start(), os);
+    if (debugging) {
+      buffer.Dispose();
     }
-#endif
+
+    RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "js-to-wasm", index,
+                              module->module->GetName(func->name_offset));
     // Set the JSFunction's machine code.
     function->set_code(*code);
   }
   return function;
 }
 
-
 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
                                     Handle<JSFunction> function,
-                                    uint32_t index) {
-  wasm::WasmFunction* func = &module->module->functions->at(index);
-
+                                    wasm::FunctionSig* sig, const char* name) {
   //----------------------------------------------------------------------------
   // Create the Graph
   //----------------------------------------------------------------------------
@@ -1894,11 +2064,11 @@
   Node* control = nullptr;
   Node* effect = nullptr;
 
-  WasmGraphBuilder builder(&zone, &jsgraph, func->sig);
+  WasmGraphBuilder builder(&zone, &jsgraph, sig);
   builder.set_control_ptr(&control);
   builder.set_effect_ptr(&effect);
   builder.set_module(module);
-  builder.BuildWasmToJSWrapper(function, func->sig);
+  builder.BuildWasmToJSWrapper(function, sig);
 
   Handle<Code> code = Handle<Code>::null();
   {
@@ -1923,26 +2093,33 @@
     }
 
     // Schedule and compile to machine code.
-    CallDescriptor* incoming = module->GetWasmCallDescriptor(&zone, func->sig);
-    CompilationInfo info("wasm-to-js", isolate, &zone);
+    CallDescriptor* incoming =
+        wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig);
     // TODO(titzer): this is technically a WASM wrapper, not a wasm function.
-    info.set_output_code_kind(Code::WASM_FUNCTION);
-    code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
-
-#ifdef ENABLE_DISASSEMBLER
-    // Disassemble the wrapper code for debugging.
-    if (!code.is_null() && FLAG_print_opt_code) {
-      Vector<char> buffer;
-      const char* name = "";
-      if (func->name_offset > 0) {
-        const byte* ptr = module->module->module_start + func->name_offset;
-        name = reinterpret_cast<const char*>(ptr);
-      }
-      SNPrintF(buffer, "WASM->JS function wrapper #%d:%s", index, name);
-      OFStream os(stdout);
-      code->Disassemble(buffer.start(), os);
-    }
+    Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION);
+    bool debugging =
+#if DEBUG
+        true;
+#else
+        FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
 #endif
+    const char* func_name = "wasm-to-js";
+    static unsigned id = 0;
+    Vector<char> buffer;
+    if (debugging) {
+      buffer = Vector<char>::New(128);
+      SNPrintF(buffer, "wasm-to-js#%d", id);
+      func_name = buffer.start();
+    }
+
+    CompilationInfo info(func_name, isolate, &zone, flags);
+    code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
+    if (debugging) {
+      buffer.Dispose();
+    }
+
+    RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "wasm-to-js", 0,
+                              name);
   }
   return code;
 }
@@ -1951,25 +2128,21 @@
 // Helper function to compile a single function.
 Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
                                  wasm::ModuleEnv* module_env,
-                                 const wasm::WasmFunction& function,
-                                 int index) {
+                                 const wasm::WasmFunction& function) {
   if (FLAG_trace_wasm_compiler || FLAG_trace_wasm_decode_time) {
-    // TODO(titzer): clean me up a bit.
     OFStream os(stdout);
-    os << "Compiling WASM function #" << index << ":";
-    if (function.name_offset > 0) {
-      os << module_env->module->GetName(function.name_offset);
-    }
+    os << "Compiling WASM function "
+       << wasm::WasmFunctionName(&function, module_env) << std::endl;
     os << std::endl;
   }
   // Initialize the function environment for decoding.
   wasm::FunctionEnv env;
   env.module = module_env;
   env.sig = function.sig;
-  env.local_int32_count = function.local_int32_count;
-  env.local_int64_count = function.local_int64_count;
-  env.local_float32_count = function.local_float32_count;
-  env.local_float64_count = function.local_float64_count;
+  env.local_i32_count = function.local_i32_count;
+  env.local_i64_count = function.local_i64_count;
+  env.local_f32_count = function.local_f32_count;
+  env.local_f64_count = function.local_f64_count;
   env.SumLocals();
 
   // Create a TF graph during decoding.
@@ -1993,35 +2166,49 @@
       os << "Compilation failed: " << result << std::endl;
     }
     // Add the function as another context for the exception
-    Vector<char> buffer;
-    SNPrintF(buffer, "Compiling WASM function #%d:%s failed:", index,
+    ScopedVector<char> buffer(128);
+    SNPrintF(buffer, "Compiling WASM function #%d:%s failed:",
+             function.func_index,
              module_env->module->GetName(function.name_offset));
     thrower.Failed(buffer.start(), result);
     return Handle<Code>::null();
   }
 
   // Run the compiler pipeline to generate machine code.
-  CallDescriptor* descriptor = const_cast<CallDescriptor*>(
-      module_env->GetWasmCallDescriptor(&zone, function.sig));
-  CompilationInfo info("wasm", isolate, &zone);
-  info.set_output_code_kind(Code::WASM_FUNCTION);
+  CallDescriptor* descriptor =
+      wasm::ModuleEnv::GetWasmCallDescriptor(&zone, function.sig);
+  if (kPointerSize == 4) {
+    descriptor = module_env->GetI32WasmCallDescriptor(&zone, descriptor);
+  }
+  Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION);
+  // add flags here if a meaningful name is helpful for debugging.
+  bool debugging =
+#if DEBUG
+      true;
+#else
+      FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
+#endif
+  const char* func_name = "wasm";
+  Vector<char> buffer;
+  if (debugging) {
+    buffer = Vector<char>::New(128);
+    SNPrintF(buffer, "WASM_function_#%d:%s", function.func_index,
+             module_env->module->GetName(function.name_offset));
+    func_name = buffer.start();
+  }
+  CompilationInfo info(func_name, isolate, &zone, flags);
+
   Handle<Code> code =
       Pipeline::GenerateCodeForTesting(&info, descriptor, &graph);
-
-#ifdef ENABLE_DISASSEMBLER
-  // Disassemble the code for debugging.
-  if (!code.is_null() && FLAG_print_opt_code) {
-    Vector<char> buffer;
-    const char* name = "";
-    if (function.name_offset > 0) {
-      const byte* ptr = module_env->module->module_start + function.name_offset;
-      name = reinterpret_cast<const char*>(ptr);
-    }
-    SNPrintF(buffer, "WASM function #%d:%s", index, name);
-    OFStream os(stdout);
-    code->Disassemble(buffer.start(), os);
+  if (debugging) {
+    buffer.Dispose();
   }
-#endif
+  if (!code.is_null()) {
+    RecordFunctionCompilation(
+        Logger::FUNCTION_TAG, &info, "WASM_function", function.func_index,
+        module_env->module->GetName(function.name_offset));
+  }
+
   return code;
 }