// 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.

#include "test/common/wasm/wasm-module-runner.h"

#include "src/execution/isolate.h"
#include "src/handles/handles.h"
#include "src/objects/heap-number-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/property-descriptor.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-interpreter.h"
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"

namespace v8 {
namespace internal {
namespace wasm {
namespace testing {

uint32_t GetInitialMemSize(const WasmModule* module) {
  return kWasmPageSize * module->initial_pages;
}

MaybeHandle<WasmModuleObject> CompileForTesting(Isolate* isolate,
                                                ErrorThrower* thrower,
                                                const ModuleWireBytes& bytes) {
  auto enabled_features = WasmFeaturesFromIsolate(isolate);
  MaybeHandle<WasmModuleObject> module = isolate->wasm_engine()->SyncCompile(
      isolate, enabled_features, thrower, bytes);
  DCHECK_EQ(thrower->error(), module.is_null());
  return module;
}

MaybeHandle<WasmInstanceObject> CompileAndInstantiateForTesting(
    Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes) {
  MaybeHandle<WasmModuleObject> module =
      CompileForTesting(isolate, thrower, bytes);
  if (module.is_null()) return {};
  return isolate->wasm_engine()->SyncInstantiate(
      isolate, thrower, module.ToHandleChecked(), {}, {});
}

std::shared_ptr<WasmModule> DecodeWasmModuleForTesting(
    Isolate* isolate, ErrorThrower* thrower, const byte* module_start,
    const byte* module_end, ModuleOrigin origin, bool verify_functions) {
  // Decode the module, but don't verify function bodies, since we'll
  // be compiling them anyway.
  auto enabled_features = WasmFeaturesFromIsolate(isolate);
  ModuleResult decoding_result = DecodeWasmModule(
      enabled_features, module_start, module_end, verify_functions, origin,
      isolate->counters(), isolate->wasm_engine()->allocator());

  if (decoding_result.failed()) {
    // Module verification failed. throw.
    thrower->CompileError("DecodeWasmModule failed: %s",
                          decoding_result.error().message().c_str());
  }

  return std::move(decoding_result).value();
}

bool InterpretWasmModuleForTesting(Isolate* isolate,
                                   Handle<WasmInstanceObject> instance,
                                   const char* name, size_t argc,
                                   WasmValue* args) {
  HandleScope handle_scope(isolate);  // Avoid leaking handles.
  WasmCodeRefScope code_ref_scope;
  MaybeHandle<WasmExportedFunction> maybe_function =
      GetExportedFunction(isolate, instance, "main");
  Handle<WasmExportedFunction> function;
  if (!maybe_function.ToHandle(&function)) {
    return false;
  }
  int function_index = function->function_index();
  FunctionSig* signature = instance->module()->functions[function_index].sig;
  size_t param_count = signature->parameter_count();
  std::unique_ptr<WasmValue[]> arguments(new WasmValue[param_count]);

  size_t arg_count = std::min(param_count, argc);
  if (arg_count > 0) {
    memcpy(arguments.get(), args, arg_count);
  }

  // Fill the parameters up with default values.
  for (size_t i = argc; i < param_count; ++i) {
    switch (signature->GetParam(i)) {
      case kWasmI32:
        arguments[i] = WasmValue(int32_t{0});
        break;
      case kWasmI64:
        arguments[i] = WasmValue(int64_t{0});
        break;
      case kWasmF32:
        arguments[i] = WasmValue(0.0f);
        break;
      case kWasmF64:
        arguments[i] = WasmValue(0.0);
        break;
      default:
        UNREACHABLE();
    }
  }

  // Don't execute more than 16k steps.
  constexpr int kMaxNumSteps = 16 * 1024;

  Zone zone(isolate->allocator(), ZONE_NAME);

  WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
  WasmInterpreter::Thread* thread = interpreter->GetThread(0);
  thread->Reset();

  // Start an activation so that we can deal with stack overflows. We do not
  // finish the activation. An activation is just part of the state of the
  // interpreter, and we do not reuse the interpreter anyways. In addition,
  // finishing the activation is not correct in all cases, e.g. when the
  // execution of the interpreter did not finish after kMaxNumSteps.
  thread->StartActivation();
  thread->InitFrame(&instance->module()->functions[function_index],
                    arguments.get());
  WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);

  if (isolate->has_pending_exception()) {
    // Stack overflow during interpretation.
    isolate->clear_pending_exception();
    return false;
  }

  return interpreter_result != WasmInterpreter::PAUSED;
}

int32_t RunWasmModuleForTesting(Isolate* isolate,
                                Handle<WasmInstanceObject> instance, int argc,
                                Handle<Object> argv[]) {
  ErrorThrower thrower(isolate, "RunWasmModule");
  return CallWasmFunctionForTesting(isolate, instance, &thrower, "main", argc,
                                    argv);
}

int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
                                const byte* module_end) {
  HandleScope scope(isolate);
  ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
  MaybeHandle<WasmInstanceObject> instance = CompileAndInstantiateForTesting(
      isolate, &thrower, ModuleWireBytes(module_start, module_end));
  if (instance.is_null()) {
    return -1;
  }
  return RunWasmModuleForTesting(isolate, instance.ToHandleChecked(), 0,
                                 nullptr);
}

int32_t CompileAndRunAsmWasmModule(Isolate* isolate, const byte* module_start,
                                   const byte* module_end) {
  HandleScope scope(isolate);
  ErrorThrower thrower(isolate, "CompileAndRunAsmWasmModule");
  MaybeHandle<AsmWasmData> data =
      isolate->wasm_engine()->SyncCompileTranslatedAsmJs(
          isolate, &thrower, ModuleWireBytes(module_start, module_end),
          Vector<const byte>(), Handle<HeapNumber>(), LanguageMode::kSloppy);
  DCHECK_EQ(thrower.error(), data.is_null());
  if (data.is_null()) return -1;

  MaybeHandle<WasmModuleObject> module =
      isolate->wasm_engine()->FinalizeTranslatedAsmJs(
          isolate, data.ToHandleChecked(), Handle<Script>::null());

  MaybeHandle<WasmInstanceObject> instance =
      isolate->wasm_engine()->SyncInstantiate(
          isolate, &thrower, module.ToHandleChecked(),
          Handle<JSReceiver>::null(), Handle<JSArrayBuffer>::null());
  DCHECK_EQ(thrower.error(), instance.is_null());
  if (instance.is_null()) return -1;

  return RunWasmModuleForTesting(isolate, instance.ToHandleChecked(), 0,
                                 nullptr);
}
WasmInterpretationResult InterpretWasmModule(
    Isolate* isolate, Handle<WasmInstanceObject> instance,
    int32_t function_index, WasmValue* args) {
  // Don't execute more than 16k steps.
  constexpr int kMaxNumSteps = 16 * 1024;

  Zone zone(isolate->allocator(), ZONE_NAME);
  v8::internal::HandleScope scope(isolate);

  WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
  WasmInterpreter::Thread* thread = interpreter->GetThread(0);
  thread->Reset();

  // Start an activation so that we can deal with stack overflows. We do not
  // finish the activation. An activation is just part of the state of the
  // interpreter, and we do not reuse the interpreter anyways. In addition,
  // finishing the activation is not correct in all cases, e.g. when the
  // execution of the interpreter did not finish after kMaxNumSteps.
  thread->StartActivation();
  thread->InitFrame(&(instance->module()->functions[function_index]), args);
  WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);

  bool stack_overflow = isolate->has_pending_exception();
  isolate->clear_pending_exception();

  if (stack_overflow) return WasmInterpretationResult::Stopped();

  if (thread->state() == WasmInterpreter::TRAPPED) {
    return WasmInterpretationResult::Trapped(thread->PossibleNondeterminism());
  }

  if (interpreter_result == WasmInterpreter::FINISHED) {
    return WasmInterpretationResult::Finished(
        thread->GetReturnValue().to<int32_t>(),
        thread->PossibleNondeterminism());
  }

  return WasmInterpretationResult::Stopped();
}

MaybeHandle<WasmExportedFunction> GetExportedFunction(
    Isolate* isolate, Handle<WasmInstanceObject> instance, const char* name) {
  Handle<JSObject> exports_object;
  Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports");
  exports_object = Handle<JSObject>::cast(
      JSObject::GetProperty(isolate, instance, exports).ToHandleChecked());

  Handle<Name> main_name = isolate->factory()->NewStringFromAsciiChecked(name);
  PropertyDescriptor desc;
  Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor(
      isolate, exports_object, main_name, &desc);
  if (!property_found.FromMaybe(false)) return {};
  if (!desc.value()->IsJSFunction()) return {};

  return Handle<WasmExportedFunction>::cast(desc.value());
}

int32_t CallWasmFunctionForTesting(Isolate* isolate,
                                   Handle<WasmInstanceObject> instance,
                                   ErrorThrower* thrower, const char* name,
                                   int argc, Handle<Object> argv[]) {
  MaybeHandle<WasmExportedFunction> maybe_export =
      GetExportedFunction(isolate, instance, name);
  Handle<WasmExportedFunction> main_export;
  if (!maybe_export.ToHandle(&main_export)) {
    return -1;
  }

  // Call the JS function.
  Handle<Object> undefined = isolate->factory()->undefined_value();
  MaybeHandle<Object> retval =
      Execution::Call(isolate, main_export, undefined, argc, argv);

  // The result should be a number.
  if (retval.is_null()) {
    DCHECK(isolate->has_pending_exception());
    isolate->clear_pending_exception();
    thrower->RuntimeError("Calling exported wasm function failed.");
    return -1;
  }
  Handle<Object> result = retval.ToHandleChecked();
  if (result->IsSmi()) {
    return Smi::ToInt(*result);
  }
  if (result->IsHeapNumber()) {
    return static_cast<int32_t>(HeapNumber::cast(*result).value());
  }
  thrower->RuntimeError(
      "Calling exported wasm function failed: Return value should be number");
  return -1;
}

void SetupIsolateForWasmModule(Isolate* isolate) {
  WasmJs::Install(isolate, true);
}

}  // namespace testing
}  // namespace wasm
}  // namespace internal
}  // namespace v8
