| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/asmjs/asm-js.h" | 5 #include "src/asmjs/asm-js.h" |
| 6 | 6 |
| 7 #include "src/api-natives.h" | 7 #include "src/api-natives.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/asmjs/asm-parser.h" |
| 9 #include "src/asmjs/asm-typer.h" | 10 #include "src/asmjs/asm-typer.h" |
| 10 #include "src/asmjs/asm-wasm-builder.h" | 11 #include "src/asmjs/asm-wasm-builder.h" |
| 11 #include "src/assert-scope.h" | 12 #include "src/assert-scope.h" |
| 12 #include "src/base/platform/elapsed-timer.h" | 13 #include "src/base/platform/elapsed-timer.h" |
| 13 #include "src/compilation-info.h" | 14 #include "src/compilation-info.h" |
| 14 #include "src/execution.h" | 15 #include "src/execution.h" |
| 15 #include "src/factory.h" | 16 #include "src/factory.h" |
| 16 #include "src/handles.h" | 17 #include "src/handles.h" |
| 17 #include "src/isolate.h" | 18 #include "src/isolate.h" |
| 18 #include "src/objects-inl.h" | 19 #include "src/objects-inl.h" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 #undef STDLIB_MATH_CONST | 159 #undef STDLIB_MATH_CONST |
| 159 default: { UNREACHABLE(); } | 160 default: { UNREACHABLE(); } |
| 160 } | 161 } |
| 161 return false; | 162 return false; |
| 162 } | 163 } |
| 163 | 164 |
| 164 } // namespace | 165 } // namespace |
| 165 | 166 |
| 166 MaybeHandle<FixedArray> AsmJs::CompileAsmViaWasm(CompilationInfo* info) { | 167 MaybeHandle<FixedArray> AsmJs::CompileAsmViaWasm(CompilationInfo* info) { |
| 167 ErrorThrower thrower(info->isolate(), "Asm.js -> WebAssembly conversion"); | 168 ErrorThrower thrower(info->isolate(), "Asm.js -> WebAssembly conversion"); |
| 169 wasm::ZoneBuffer* module = nullptr; |
| 170 wasm::ZoneBuffer* asm_offsets = nullptr; |
| 171 Handle<FixedArray> uses_array; |
| 172 Handle<FixedArray> foreign_globals; |
| 168 base::ElapsedTimer asm_wasm_timer; | 173 base::ElapsedTimer asm_wasm_timer; |
| 169 asm_wasm_timer.Start(); | 174 asm_wasm_timer.Start(); |
| 170 wasm::AsmWasmBuilder builder(info); | 175 wasm::AsmWasmBuilder builder(info); |
| 171 Handle<FixedArray> foreign_globals; | 176 if (FLAG_fast_validate_asm) { |
| 172 auto asm_wasm_result = builder.Run(&foreign_globals); | 177 wasm::AsmJsParser parser(info->isolate(), info->zone(), info->script(), |
| 173 if (!asm_wasm_result.success) { | 178 info->literal()->start_position(), |
| 174 DCHECK(!info->isolate()->has_pending_exception()); | 179 info->literal()->end_position()); |
| 175 if (!FLAG_suppress_asm_messages) { | 180 if (!parser.Run()) { |
| 176 MessageHandler::ReportMessage(info->isolate(), | 181 DCHECK(!info->isolate()->has_pending_exception()); |
| 177 builder.typer()->message_location(), | 182 if (!FLAG_suppress_asm_messages) { |
| 178 builder.typer()->error_message()); | 183 MessageLocation location(info->script(), parser.failure_location(), |
| 184 parser.failure_location()); |
| 185 Handle<String> message = |
| 186 info->isolate() |
| 187 ->factory() |
| 188 ->NewStringFromUtf8(CStrVector(parser.failure_message())) |
| 189 .ToHandleChecked(); |
| 190 Handle<JSMessageObject> error_message = |
| 191 MessageHandler::MakeMessageObject( |
| 192 info->isolate(), MessageTemplate::kAsmJsInvalid, &location, |
| 193 message, Handle<JSArray>::null()); |
| 194 error_message->set_error_level(v8::Isolate::kMessageWarning); |
| 195 MessageHandler::ReportMessage(info->isolate(), &location, |
| 196 error_message); |
| 197 } |
| 198 return MaybeHandle<FixedArray>(); |
| 179 } | 199 } |
| 180 return MaybeHandle<FixedArray>(); | 200 Zone* zone = info->zone(); |
| 201 module = new (zone) wasm::ZoneBuffer(zone); |
| 202 parser.module_builder()->WriteTo(*module); |
| 203 asm_offsets = new (zone) wasm::ZoneBuffer(zone); |
| 204 parser.module_builder()->WriteAsmJsOffsetTable(*asm_offsets); |
| 205 // TODO(bradnelson): Remove foreign_globals plumbing (as we don't need it |
| 206 // for the new parser). |
| 207 foreign_globals = info->isolate()->factory()->NewFixedArray(0); |
| 208 uses_array = info->isolate()->factory()->NewFixedArray( |
| 209 static_cast<int>(parser.stdlib_uses()->size())); |
| 210 int count = 0; |
| 211 for (auto i : *parser.stdlib_uses()) { |
| 212 uses_array->set(count++, Smi::FromInt(i)); |
| 213 } |
| 214 } else { |
| 215 auto asm_wasm_result = builder.Run(&foreign_globals); |
| 216 if (!asm_wasm_result.success) { |
| 217 DCHECK(!info->isolate()->has_pending_exception()); |
| 218 if (!FLAG_suppress_asm_messages) { |
| 219 MessageHandler::ReportMessage(info->isolate(), |
| 220 builder.typer()->message_location(), |
| 221 builder.typer()->error_message()); |
| 222 } |
| 223 return MaybeHandle<FixedArray>(); |
| 224 } |
| 225 module = asm_wasm_result.module_bytes; |
| 226 asm_offsets = asm_wasm_result.asm_offset_table; |
| 227 wasm::AsmTyper::StdlibSet uses = builder.typer()->StdlibUses(); |
| 228 uses_array = info->isolate()->factory()->NewFixedArray( |
| 229 static_cast<int>(uses.size())); |
| 230 int count = 0; |
| 231 for (auto i : uses) { |
| 232 uses_array->set(count++, Smi::FromInt(i)); |
| 233 } |
| 181 } | 234 } |
| 235 |
| 182 double asm_wasm_time = asm_wasm_timer.Elapsed().InMillisecondsF(); | 236 double asm_wasm_time = asm_wasm_timer.Elapsed().InMillisecondsF(); |
| 183 | |
| 184 wasm::ZoneBuffer* module = asm_wasm_result.module_bytes; | |
| 185 wasm::ZoneBuffer* asm_offsets = asm_wasm_result.asm_offset_table; | |
| 186 Vector<const byte> asm_offsets_vec(asm_offsets->begin(), | 237 Vector<const byte> asm_offsets_vec(asm_offsets->begin(), |
| 187 static_cast<int>(asm_offsets->size())); | 238 static_cast<int>(asm_offsets->size())); |
| 188 | 239 |
| 189 base::ElapsedTimer compile_timer; | 240 base::ElapsedTimer compile_timer; |
| 190 compile_timer.Start(); | 241 compile_timer.Start(); |
| 191 MaybeHandle<JSObject> compiled = SyncCompileTranslatedAsmJs( | 242 MaybeHandle<JSObject> compiled = SyncCompileTranslatedAsmJs( |
| 192 info->isolate(), &thrower, | 243 info->isolate(), &thrower, |
| 193 wasm::ModuleWireBytes(module->begin(), module->end()), info->script(), | 244 wasm::ModuleWireBytes(module->begin(), module->end()), info->script(), |
| 194 asm_offsets_vec); | 245 asm_offsets_vec); |
| 195 DCHECK(!compiled.is_null()); | 246 DCHECK(!compiled.is_null()); |
| 196 double compile_time = compile_timer.Elapsed().InMillisecondsF(); | 247 double compile_time = compile_timer.Elapsed().InMillisecondsF(); |
| 197 DCHECK_GE(module->end(), module->begin()); | 248 DCHECK_GE(module->end(), module->begin()); |
| 198 uintptr_t wasm_size = module->end() - module->begin(); | 249 uintptr_t wasm_size = module->end() - module->begin(); |
| 199 | 250 |
| 200 wasm::AsmTyper::StdlibSet uses = builder.typer()->StdlibUses(); | |
| 201 Handle<FixedArray> uses_array = | |
| 202 info->isolate()->factory()->NewFixedArray(static_cast<int>(uses.size())); | |
| 203 int count = 0; | |
| 204 for (auto i : uses) { | |
| 205 uses_array->set(count++, Smi::FromInt(i)); | |
| 206 } | |
| 207 | |
| 208 Handle<FixedArray> result = | 251 Handle<FixedArray> result = |
| 209 info->isolate()->factory()->NewFixedArray(kWasmDataEntryCount); | 252 info->isolate()->factory()->NewFixedArray(kWasmDataEntryCount); |
| 210 result->set(kWasmDataCompiledModule, *compiled.ToHandleChecked()); | 253 result->set(kWasmDataCompiledModule, *compiled.ToHandleChecked()); |
| 211 result->set(kWasmDataForeignGlobals, *foreign_globals); | 254 result->set(kWasmDataForeignGlobals, *foreign_globals); |
| 212 result->set(kWasmDataUsesArray, *uses_array); | 255 result->set(kWasmDataUsesArray, *uses_array); |
| 213 result->set(kWasmDataScript, *info->script()); | 256 result->set(kWasmDataScript, *info->script()); |
| 214 result->set(kWasmDataScriptPosition, | 257 result->set(kWasmDataScriptPosition, |
| 215 Smi::FromInt(info->literal()->position())); | 258 Smi::FromInt(info->literal()->position())); |
| 216 | 259 |
| 217 MessageLocation location(info->script(), info->literal()->position(), | 260 MessageLocation location(info->script(), info->literal()->position(), |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 foreign, NONE); | 319 foreign, NONE); |
| 277 } | 320 } |
| 278 | 321 |
| 279 i::MaybeHandle<i::Object> maybe_module_object = | 322 i::MaybeHandle<i::Object> maybe_module_object = |
| 280 i::wasm::SyncInstantiate(isolate, &thrower, module, ffi_object, memory); | 323 i::wasm::SyncInstantiate(isolate, &thrower, module, ffi_object, memory); |
| 281 if (maybe_module_object.is_null()) { | 324 if (maybe_module_object.is_null()) { |
| 282 return MaybeHandle<Object>(); | 325 return MaybeHandle<Object>(); |
| 283 } | 326 } |
| 284 i::Handle<i::Object> module_object = maybe_module_object.ToHandleChecked(); | 327 i::Handle<i::Object> module_object = maybe_module_object.ToHandleChecked(); |
| 285 | 328 |
| 286 i::Handle<i::Name> init_name(isolate->factory()->InternalizeUtf8String( | 329 if (!FLAG_fast_validate_asm) { |
| 287 wasm::AsmWasmBuilder::foreign_init_name)); | 330 i::Handle<i::Name> init_name(isolate->factory()->InternalizeUtf8String( |
| 288 i::Handle<i::Object> init = | 331 wasm::AsmWasmBuilder::foreign_init_name)); |
| 289 i::Object::GetProperty(module_object, init_name).ToHandleChecked(); | 332 i::Handle<i::Object> init = |
| 333 i::Object::GetProperty(module_object, init_name).ToHandleChecked(); |
| 290 | 334 |
| 291 i::Handle<i::Object> undefined(isolate->heap()->undefined_value(), isolate); | 335 i::Handle<i::Object> undefined(isolate->heap()->undefined_value(), isolate); |
| 292 i::Handle<i::Object>* foreign_args_array = | 336 i::Handle<i::Object>* foreign_args_array = |
| 293 new i::Handle<i::Object>[foreign_globals->length()]; | 337 new i::Handle<i::Object>[foreign_globals->length()]; |
| 294 for (int j = 0; j < foreign_globals->length(); j++) { | 338 for (int j = 0; j < foreign_globals->length(); j++) { |
| 295 if (!foreign.is_null()) { | 339 if (!foreign.is_null()) { |
| 296 i::MaybeHandle<i::Name> name = i::Object::ToName( | 340 i::MaybeHandle<i::Name> name = i::Object::ToName( |
| 297 isolate, i::Handle<i::Object>(foreign_globals->get(j), isolate)); | 341 isolate, i::Handle<i::Object>(foreign_globals->get(j), isolate)); |
| 298 if (!name.is_null()) { | 342 if (!name.is_null()) { |
| 299 i::MaybeHandle<i::Object> val = | 343 i::MaybeHandle<i::Object> val = |
| 300 i::Object::GetProperty(foreign, name.ToHandleChecked()); | 344 i::Object::GetProperty(foreign, name.ToHandleChecked()); |
| 301 if (!val.is_null()) { | 345 if (!val.is_null()) { |
| 302 foreign_args_array[j] = val.ToHandleChecked(); | 346 foreign_args_array[j] = val.ToHandleChecked(); |
| 303 continue; | 347 continue; |
| 348 } |
| 304 } | 349 } |
| 305 } | 350 } |
| 351 foreign_args_array[j] = undefined; |
| 306 } | 352 } |
| 307 foreign_args_array[j] = undefined; | 353 i::MaybeHandle<i::Object> retval = |
| 354 i::Execution::Call(isolate, init, undefined, foreign_globals->length(), |
| 355 foreign_args_array); |
| 356 delete[] foreign_args_array; |
| 357 DCHECK(!retval.is_null()); |
| 308 } | 358 } |
| 309 i::MaybeHandle<i::Object> retval = i::Execution::Call( | |
| 310 isolate, init, undefined, foreign_globals->length(), foreign_args_array); | |
| 311 delete[] foreign_args_array; | |
| 312 DCHECK(!retval.is_null()); | |
| 313 | 359 |
| 314 i::Handle<i::Name> single_function_name( | 360 i::Handle<i::Name> single_function_name( |
| 315 isolate->factory()->InternalizeUtf8String( | 361 isolate->factory()->InternalizeUtf8String( |
| 316 wasm::AsmWasmBuilder::single_function_name)); | 362 wasm::AsmWasmBuilder::single_function_name)); |
| 317 i::MaybeHandle<i::Object> single_function = | 363 i::MaybeHandle<i::Object> single_function = |
| 318 i::Object::GetProperty(module_object, single_function_name); | 364 i::Object::GetProperty(module_object, single_function_name); |
| 319 if (!single_function.is_null() && | 365 if (!single_function.is_null() && |
| 320 !single_function.ToHandleChecked()->IsUndefined(isolate)) { | 366 !single_function.ToHandleChecked()->IsUndefined(isolate)) { |
| 321 return single_function; | 367 return single_function; |
| 322 } | 368 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 346 MessageHandler::ReportMessage(isolate, &location, message); | 392 MessageHandler::ReportMessage(isolate, &location, message); |
| 347 } | 393 } |
| 348 | 394 |
| 349 Handle<String> exports_name = | 395 Handle<String> exports_name = |
| 350 isolate->factory()->InternalizeUtf8String("exports"); | 396 isolate->factory()->InternalizeUtf8String("exports"); |
| 351 return i::Object::GetProperty(module_object, exports_name); | 397 return i::Object::GetProperty(module_object, exports_name); |
| 352 } | 398 } |
| 353 | 399 |
| 354 } // namespace internal | 400 } // namespace internal |
| 355 } // namespace v8 | 401 } // namespace v8 |
| OLD | NEW |