Commit 9d6014ad authored by mtrofin's avatar mtrofin Committed by Commit bot

Revert "Revert "[wasm] Complete separation of compilation and instantiation""

This reverts commit 1eb1dfab.

The original compilation separation change avoided associating a heap
for the wasm instance if memory was not provided, nor needed. The
grow memory CL assumed the old behavior, where a memory buffer was
always present, but may have had a zero size.

The 2CLS  landed shortly after one another. We decided to treat the
grow memory as the race condition winner, so this CL here re-lands
compilation separation, plus adjusts grow memory to deal with
the undefined mem buffer.

BUG=

Review-Url: https://codereview.chromium.org/2102193003
Cr-Commit-Position: refs/heads/master@{#37352}
parent 1eb1dfab
......@@ -2955,29 +2955,31 @@ void WasmGraphBuilder::SetSourcePosition(Node* node,
}
static void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
CompilationInfo* info,
Isolate* isolate, Handle<Code> code,
const char* message, uint32_t index,
wasm::WasmName func_name) {
Isolate* isolate = info->isolate();
if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
ScopedVector<char> buffer(128);
SNPrintF(buffer, "%s#%d:%.*s", message, index, func_name.length(),
func_name.start());
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, AbstractCode::cast(*code), *shared,
*script_str, 0, 0));
}
}
Handle<JSFunction> CompileJSToWasmWrapper(
Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name,
Handle<Code> wasm_code, Handle<JSObject> module_object, uint32_t index) {
const wasm::WasmName& module_name,
const wasm::WasmName& func_name) {
DCHECK(isolate->logger()->is_logging_code_events() ||
isolate->is_profiling());
ScopedVector<char> buffer(128);
SNPrintF(buffer, "%s#%d:%.*s:%.*s", message, index, module_name.length(),
module_name.start(), func_name.length(), func_name.start());
Handle<String> name_str =
isolate->factory()->NewStringFromAsciiChecked(buffer.start());
Handle<String> script_str =
isolate->factory()->NewStringFromAsciiChecked("(WASM)");
Handle<SharedFunctionInfo> shared =
isolate->factory()->NewSharedFunctionInfo(name_str, code, false);
PROFILE(isolate, CodeCreateEvent(tag, AbstractCode::cast(*code), *shared,
*script_str, 0, 0));
}
Handle<JSFunction> CompileJSToWasmWrapper(Isolate* isolate,
wasm::ModuleEnv* module,
Handle<String> name,
Handle<Code> wasm_code,
uint32_t index) {
const wasm::WasmFunction* func = &module->module->functions[index];
//----------------------------------------------------------------------------
......@@ -2990,7 +2992,6 @@ Handle<JSFunction> CompileJSToWasmWrapper(
shared->set_internal_formal_parameter_count(params);
Handle<JSFunction> function = isolate->factory()->NewFunction(
isolate->wasm_function_map(), name, MaybeHandle<Code>());
function->SetInternalField(0, *module_object);
function->set_shared(*shared);
//----------------------------------------------------------------------------
......@@ -3056,9 +3057,13 @@ Handle<JSFunction> CompileJSToWasmWrapper(
buffer.Dispose();
}
RecordFunctionCompilation(
CodeEventListener::FUNCTION_TAG, &info, "js-to-wasm", index,
module->module->GetName(func->name_offset, func->name_length));
if (isolate->logger()->is_logging_code_events() ||
isolate->is_profiling()) {
RecordFunctionCompilation(
CodeEventListener::FUNCTION_TAG, isolate, code, "js-to-wasm", index,
wasm::WasmName("export"),
module->module->GetName(func->name_offset, func->name_length));
}
// Set the JSFunction's machine code.
function->set_code(*code);
}
......@@ -3067,9 +3072,9 @@ Handle<JSFunction> CompileJSToWasmWrapper(
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate,
Handle<JSFunction> function,
wasm::FunctionSig* sig,
wasm::WasmName module_name,
wasm::WasmName function_name) {
wasm::FunctionSig* sig, uint32_t index,
Handle<String> import_module,
MaybeHandle<String> import_function) {
//----------------------------------------------------------------------------
// Create the Graph
//----------------------------------------------------------------------------
......@@ -3128,10 +3133,21 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate,
if (debugging) {
buffer.Dispose();
}
RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info,
"wasm-to-js", 0, module_name);
}
if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
const char* function_name = nullptr;
int function_name_size = 0;
if (!import_function.is_null()) {
Handle<String> handle = import_function.ToHandleChecked();
function_name = handle->ToCString().get();
function_name_size = handle->length();
}
RecordFunctionCompilation(
CodeEventListener::FUNCTION_TAG, isolate, code, "wasm-to-js", index,
{import_module->ToCString().get(), import_module->length()},
{function_name, function_name_size});
}
return code;
}
......@@ -3294,11 +3310,14 @@ Handle<Code> WasmCompilationUnit::FinishCompilation() {
Handle<Code> code = info_.code();
DCHECK(!code.is_null());
RecordFunctionCompilation(
CodeEventListener::FUNCTION_TAG, &info_, "WASM_function",
function_->func_index,
module_env_->module->GetName(function_->name_offset,
function_->name_length));
if (isolate_->logger()->is_logging_code_events() ||
isolate_->is_profiling()) {
RecordFunctionCompilation(
CodeEventListener::FUNCTION_TAG, isolate_, code, "WASM_function",
function_->func_index, wasm::WasmName("module"),
module_env_->module->GetName(function_->name_offset,
function_->name_length));
}
if (FLAG_trace_wasm_decode_time) {
double compile_ms = compile_timer.Elapsed().InMillisecondsF();
......
......@@ -79,15 +79,17 @@ class WasmCompilationUnit final {
// Wraps a JS function, producing a code object that can be called from WASM.
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate,
Handle<JSFunction> function,
wasm::FunctionSig* sig,
wasm::WasmName module_name,
wasm::WasmName function_name);
wasm::FunctionSig* sig, uint32_t index,
Handle<String> import_module,
MaybeHandle<String> import_function);
// Wraps a given wasm code object, producing a JSFunction that can be called
// from JavaScript.
Handle<JSFunction> CompileJSToWasmWrapper(
Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name,
Handle<Code> wasm_code, Handle<JSObject> module_object, uint32_t index);
Handle<JSFunction> CompileJSToWasmWrapper(Isolate* isolate,
wasm::ModuleEnv* module,
Handle<String> name,
Handle<Code> wasm_code,
uint32_t index);
// Abstracts details of building TurboFan graph nodes for WASM to separate
// the WASM decoder from the internal details of TurboFan.
......
......@@ -2306,12 +2306,24 @@ Handle<Object> FixedArray::get(FixedArray* array, int index, Isolate* isolate) {
return handle(array->get(index), isolate);
}
template <class T>
MaybeHandle<T> FixedArray::GetValue(int index) const {
Object* obj = get(index);
if (obj->IsUndefined(GetIsolate())) return MaybeHandle<T>();
return Handle<T>(T::cast(obj));
}
template <class T>
Handle<T> FixedArray::GetValueChecked(int index) const {
Object* obj = get(index);
CHECK(!obj->IsUndefined(GetIsolate()));
return Handle<T>(T::cast(obj));
}
bool FixedArray::is_the_hole(int index) {
return get(index) == GetHeap()->the_hole_value();
}
void FixedArray::set(int index, Smi* value) {
DCHECK(map() != GetHeap()->fixed_cow_array_map());
DCHECK(index >= 0 && index < this->length());
......@@ -3981,6 +3993,9 @@ byte ByteArray::get(int index) {
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
}
const byte* ByteArray::data() const {
return reinterpret_cast<const byte*>(FIELD_ADDR_CONST(this, kHeaderSize));
}
void ByteArray::set(int index, byte value) {
DCHECK(index >= 0 && index < this->length());
......
......@@ -2644,6 +2644,12 @@ class FixedArray: public FixedArrayBase {
inline Object* get(int index) const;
static inline Handle<Object> get(FixedArray* array, int index,
Isolate* isolate);
template <class T>
MaybeHandle<T> GetValue(int index) const;
template <class T>
Handle<T> GetValueChecked(int index) const;
// Setter that uses write barrier.
inline void set(int index, Object* value);
inline bool is_the_hole(int index);
......@@ -4420,6 +4426,7 @@ class ByteArray: public FixedArrayBase {
// Setter and getter.
inline byte get(int index);
inline void set(int index, byte value);
inline const byte* data() const;
// Copy in / copy out whole byte slices.
inline void copy_out(int index, byte* buffer, int length);
......
......@@ -39,13 +39,11 @@ RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
// Get mem buffer associated with module object
Object* obj = module_object->GetInternalField(kWasmMemArrayBuffer);
Handle<JSArrayBuffer> old_buffer =
Handle<JSArrayBuffer>(JSArrayBuffer::cast(obj));
if (old_buffer->byte_length()->Number() == 0) {
if (obj->IsUndefined(isolate)) {
// If module object does not have linear memory associated with it,
// Allocate new array buffer of given size.
old_mem_start = static_cast<Address>(old_buffer->backing_store());
old_mem_start = nullptr;
old_size = 0;
// TODO(gdeepti): Fix bounds check to take into account size of memtype.
new_size = delta_pages * wasm::WasmModule::kPageSize;
......@@ -67,8 +65,15 @@ RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
}
#endif
} else {
Handle<JSArrayBuffer> old_buffer =
Handle<JSArrayBuffer>(JSArrayBuffer::cast(obj));
old_mem_start = static_cast<Address>(old_buffer->backing_store());
old_size = old_buffer->byte_length()->Number();
// If the old memory was zero-sized, we should have been in the
// "undefined" case above.
DCHECK_NOT_NULL(old_mem_start);
DCHECK_NE(0, old_size);
new_size = old_size + delta_pages * wasm::WasmModule::kPageSize;
if (new_size >
wasm::WasmModule::kMaxMemPages * wasm::WasmModule::kPageSize) {
......
......@@ -14,7 +14,7 @@ namespace internal {
template <typename T>
class Signature : public ZoneObject {
public:
Signature(size_t return_count, size_t parameter_count, T* reps)
Signature(size_t return_count, size_t parameter_count, const T* reps)
: return_count_(return_count),
parameter_count_(parameter_count),
reps_(reps) {}
......@@ -32,6 +32,8 @@ class Signature : public ZoneObject {
return reps_[index];
}
const T* raw_data() const { return reps_; }
// For incrementally building signatures.
class Builder {
public:
......@@ -71,7 +73,7 @@ class Signature : public ZoneObject {
protected:
size_t return_count_;
size_t parameter_count_;
T* reps_;
const T* reps_;
};
} // namespace internal
......
......@@ -197,9 +197,14 @@ i::MaybeHandle<i::JSObject> InstantiateModuleCommon(
memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj));
}
object = result.val->Instantiate(isolate, ffi, memory);
if (!object.is_null()) {
args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked()));
i::MaybeHandle<i::FixedArray> compiled_module =
result.val->CompileFunctions(isolate);
if (!compiled_module.is_null()) {
object = i::wasm::WasmModule::Instantiate(
isolate, compiled_module.ToHandleChecked(), ffi, memory);
if (!object.is_null()) {
args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked()));
}
}
}
......
This diff is collapsed.
......@@ -224,10 +224,12 @@ struct WasmModule {
}
// Creates a new instantiation of the module in the given isolate.
MaybeHandle<JSObject> Instantiate(Isolate* isolate, Handle<JSReceiver> ffi,
Handle<JSArrayBuffer> memory) const;
static MaybeHandle<JSObject> Instantiate(Isolate* isolate,
Handle<FixedArray> compiled_module,
Handle<JSReceiver> ffi,
Handle<JSArrayBuffer> memory);
Handle<FixedArray> CompileFunctions(Isolate* isolate) const;
MaybeHandle<FixedArray> CompileFunctions(Isolate* isolate) const;
uint32_t FunctionTableSize() const {
if (indirect_table_size > 0) {
......
......@@ -186,10 +186,9 @@ class TestingModule : public ModuleEnv {
Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
*v8::Local<v8::Function>::Cast(CompileRun(source))));
uint32_t index = AddFunction(sig, Handle<Code>::null());
WasmName module_name = ArrayVector("test");
WasmName function_name;
Handle<Code> code = CompileWasmToJSWrapper(isolate_, jsfunc, sig,
module_name, function_name);
Handle<Code> code =
CompileWasmToJSWrapper(isolate_, jsfunc, sig, index,
Handle<String>::null(), Handle<String>::null());
instance->function_code[index] = code;
return index;
}
......@@ -200,8 +199,10 @@ class TestingModule : public ModuleEnv {
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,
module_object, index);
Handle<JSFunction> ret =
compiler::CompileJSToWasmWrapper(isolate_, this, name, code, index);
ret->SetInternalField(0, *module_object);
return ret;
}
void SetFunctionCode(uint32_t index, Handle<Code> code) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment