diff options
Diffstat (limited to 'deps/v8/src/asmjs')
-rw-r--r-- | deps/v8/src/asmjs/OWNERS | 2 | ||||
-rw-r--r-- | deps/v8/src/asmjs/asm-js.cc | 33 | ||||
-rw-r--r-- | deps/v8/src/asmjs/asm-parser.cc | 68 | ||||
-rw-r--r-- | deps/v8/src/asmjs/asm-parser.h | 57 | ||||
-rw-r--r-- | deps/v8/src/asmjs/asm-scanner.cc | 5 | ||||
-rw-r--r-- | deps/v8/src/asmjs/asm-scanner.h | 2 | ||||
-rw-r--r-- | deps/v8/src/asmjs/asm-types.cc | 1 |
7 files changed, 105 insertions, 63 deletions
diff --git a/deps/v8/src/asmjs/OWNERS b/deps/v8/src/asmjs/OWNERS index 4f54661aeb..e40f5b57f3 100644 --- a/deps/v8/src/asmjs/OWNERS +++ b/deps/v8/src/asmjs/OWNERS @@ -6,3 +6,5 @@ clemensh@chromium.org mtrofin@chromium.org rossberg@chromium.org titzer@chromium.org + +# COMPONENT: Blink>JavaScript>WebAssembly diff --git a/deps/v8/src/asmjs/asm-js.cc b/deps/v8/src/asmjs/asm-js.cc index 516bce2543..fb257e316e 100644 --- a/deps/v8/src/asmjs/asm-js.cc +++ b/deps/v8/src/asmjs/asm-js.cc @@ -4,8 +4,6 @@ #include "src/asmjs/asm-js.h" -#include "src/api-natives.h" -#include "src/api.h" #include "src/asmjs/asm-names.h" #include "src/asmjs/asm-parser.h" #include "src/assert-scope.h" @@ -17,7 +15,8 @@ #include "src/handles.h" #include "src/isolate.h" #include "src/objects-inl.h" -#include "src/objects.h" +#include "src/parsing/scanner-character-streams.h" +#include "src/parsing/scanner.h" #include "src/wasm/module-decoder.h" #include "src/wasm/wasm-js.h" @@ -54,12 +53,12 @@ bool IsStdlibMemberValid(Isolate* isolate, Handle<JSReceiver> stdlib, bool* is_typed_array) { switch (member) { case wasm::AsmJsParser::StandardMember::kInfinity: { - Handle<Name> name = isolate->factory()->infinity_string(); + Handle<Name> name = isolate->factory()->Infinity_string(); Handle<Object> value = JSReceiver::GetDataProperty(stdlib, name); return value->IsNumber() && std::isinf(value->Number()); } case wasm::AsmJsParser::StandardMember::kNaN: { - Handle<Name> name = isolate->factory()->nan_string(); + Handle<Name> name = isolate->factory()->NaN_string(); Handle<Object> value = JSReceiver::GetDataProperty(stdlib, name); return value->IsNaN(); } @@ -105,7 +104,6 @@ bool IsStdlibMemberValid(Isolate* isolate, Handle<JSReceiver> stdlib, #undef STDLIB_ARRAY_TYPE } UNREACHABLE(); - return false; } void Report(Handle<Script> script, int position, Vector<const char> text, @@ -193,9 +191,11 @@ MaybeHandle<FixedArray> AsmJs::CompileAsmViaWasm(CompilationInfo* info) { Zone* compile_zone = info->zone(); Zone translate_zone(info->isolate()->allocator(), ZONE_NAME); - wasm::AsmJsParser parser(info->isolate(), &translate_zone, info->script(), - info->literal()->start_position(), - info->literal()->end_position()); + std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For( + handle(String::cast(info->script()->source())), + info->literal()->start_position(), info->literal()->end_position())); + uintptr_t stack_limit = info->isolate()->stack_guard()->real_climit(); + wasm::AsmJsParser parser(&translate_zone, stack_limit, std::move(stream)); if (!parser.Run()) { DCHECK(!info->isolate()->has_pending_exception()); ReportCompilationFailure(info->script(), parser.failure_location(), @@ -277,7 +277,7 @@ MaybeHandle<Object> AsmJs::InstantiateAsmWasm(Isolate* isolate, ReportInstantiationFailure(script, position, "Requires standard library"); return MaybeHandle<Object>(); } - int member_id = Smi::cast(stdlib_uses->get(i))->value(); + int member_id = Smi::ToInt(stdlib_uses->get(i)); wasm::AsmJsParser::StandardMember member = static_cast<wasm::AsmJsParser::StandardMember>(member_id); if (!IsStdlibMemberValid(isolate, stdlib, member, @@ -287,16 +287,6 @@ MaybeHandle<Object> AsmJs::InstantiateAsmWasm(Isolate* isolate, } } - // Create the ffi object for foreign functions {"": foreign}. - Handle<JSObject> ffi_object; - if (!foreign.is_null()) { - Handle<JSFunction> object_function = Handle<JSFunction>( - isolate->native_context()->object_function(), isolate); - ffi_object = isolate->factory()->NewJSObject(object_function); - JSObject::AddProperty(ffi_object, isolate->factory()->empty_string(), - foreign, NONE); - } - // Check that a valid heap buffer is provided if required. if (stdlib_use_of_typed_array_present) { if (memory.is_null()) { @@ -314,8 +304,9 @@ MaybeHandle<Object> AsmJs::InstantiateAsmWasm(Isolate* isolate, wasm::ErrorThrower thrower(isolate, "AsmJs::Instantiate"); MaybeHandle<Object> maybe_module_object = - wasm::SyncInstantiate(isolate, &thrower, module, ffi_object, memory); + wasm::SyncInstantiate(isolate, &thrower, module, foreign, memory); if (maybe_module_object.is_null()) { + DCHECK(!isolate->has_pending_exception()); thrower.Reset(); // Ensure exceptions do not propagate. ReportInstantiationFailure(script, position, "Internal wasm failure"); return MaybeHandle<Object>(); diff --git a/deps/v8/src/asmjs/asm-parser.cc b/deps/v8/src/asmjs/asm-parser.cc index 51b8f7bbc2..1e5f7d5dc4 100644 --- a/deps/v8/src/asmjs/asm-parser.cc +++ b/deps/v8/src/asmjs/asm-parser.cc @@ -11,9 +11,8 @@ #include "src/asmjs/asm-js.h" #include "src/asmjs/asm-types.h" -#include "src/objects-inl.h" -#include "src/objects.h" -#include "src/parsing/scanner-character-streams.h" +#include "src/base/optional.h" +#include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker. #include "src/parsing/scanner.h" #include "src/wasm/wasm-opcodes.h" @@ -68,16 +67,16 @@ namespace wasm { #define TOK(name) AsmJsScanner::kToken_##name -AsmJsParser::AsmJsParser(Isolate* isolate, Zone* zone, Handle<Script> script, - int start, int end) +AsmJsParser::AsmJsParser(Zone* zone, uintptr_t stack_limit, + std::unique_ptr<Utf16CharacterStream> stream) : zone_(zone), module_builder_(new (zone) WasmModuleBuilder(zone)), return_type_(nullptr), - stack_limit_(isolate->stack_guard()->real_climit()), + stack_limit_(stack_limit), global_var_info_(zone), local_var_info_(zone), failed_(false), - failure_location_(start), + failure_location_(kNoSourcePosition), stdlib_name_(kTokenNone), foreign_name_(kTokenNone), heap_name_(kTokenNone), @@ -89,9 +88,6 @@ AsmJsParser::AsmJsParser(Isolate* isolate, Zone* zone, Handle<Script> script, pending_label_(0), global_imports_(zone) { InitializeStdlibTypes(); - Handle<String> source(String::cast(script->source()), isolate); - std::unique_ptr<Utf16CharacterStream> stream( - ScannerStream::For(source, start, end)); scanner_.SetStream(std::move(stream)); } @@ -144,8 +140,8 @@ void AsmJsParser::InitializeStdlibTypes() { stdlib_fround_ = AsmType::FroundType(zone()); } -FunctionSig* AsmJsParser::ConvertSignature( - AsmType* return_type, const std::vector<AsmType*>& params) { +FunctionSig* AsmJsParser::ConvertSignature(AsmType* return_type, + const ZoneVector<AsmType*>& params) { FunctionSig::Builder sig_builder( zone(), !return_type->IsA(AsmType::Void()) ? 1 : 0, params.size()); for (auto param : params) { @@ -215,7 +211,6 @@ wasm::AsmJsParser::VarInfo* AsmJsParser::GetVarInfo( return &local_var_info_[index]; } UNREACHABLE(); - return nullptr; } uint32_t AsmJsParser::VarIndex(VarInfo* info) { @@ -348,9 +343,15 @@ void AsmJsParser::ValidateModule() { if (info.kind == VarKind::kTable && !info.function_defined) { FAIL("Undefined function table"); } + if (info.kind == VarKind::kImportedFunction && !info.function_defined) { + // For imported functions without a single call site, we insert a dummy + // import here to preserve the fact that there actually was an import. + FunctionSig* void_void_sig = FunctionSig::Builder(zone(), 0, 0).Build(); + module_builder_->AddImport(info.import->function_name, void_void_sig); + } } - // Add start function to init things. + // Add start function to initialize things. WasmFunctionBuilder* start = module_builder_->AddFunction(); module_builder_->MarkStartFunction(start); for (auto& global_import : global_imports_) { @@ -725,9 +726,9 @@ void AsmJsParser::ValidateFunction() { int start_position = static_cast<int>(scanner_.Position()); current_function_builder_->SetAsmFunctionStartPosition(start_position); - std::vector<AsmType*> params; + CachedVector<AsmType*> params(cached_asm_type_p_vectors_); ValidateFunctionParams(¶ms); - std::vector<ValueType> locals; + CachedVector<ValueType> locals(cached_valuetype_vectors_); ValidateFunctionLocals(params.size(), &locals); function_temp_locals_offset_ = static_cast<uint32_t>( @@ -787,13 +788,14 @@ void AsmJsParser::ValidateFunction() { } // 6.4 ValidateFunction -void AsmJsParser::ValidateFunctionParams(std::vector<AsmType*>* params) { +void AsmJsParser::ValidateFunctionParams(ZoneVector<AsmType*>* params) { // TODO(bradnelson): Do this differently so that the scanner doesn't need to // have a state transition that needs knowledge of how the scanner works // inside. scanner_.EnterLocalScope(); EXPECT_TOKEN('('); - std::vector<AsmJsScanner::token_t> function_parameters; + CachedVector<AsmJsScanner::token_t> function_parameters( + cached_token_t_vectors_); while (!failed_ && !Peek(')')) { if (!scanner_.IsLocal()) { FAIL("Expected parameter name"); @@ -847,8 +849,8 @@ void AsmJsParser::ValidateFunctionParams(std::vector<AsmType*>* params) { } // 6.4 ValidateFunction - locals -void AsmJsParser::ValidateFunctionLocals( - size_t param_count, std::vector<ValueType>* locals) { +void AsmJsParser::ValidateFunctionLocals(size_t param_count, + ZoneVector<ValueType>* locals) { // Local Variables. while (Peek(TOK(var))) { scanner_.EnterLocalScope(); @@ -1262,7 +1264,7 @@ void AsmJsParser::SwitchStatement() { Begin(pending_label_); pending_label_ = 0; // TODO(bradnelson): Make less weird. - std::vector<int32_t> cases; + CachedVector<int32_t> cases(cached_int_vectors_); GatherCases(&cases); EXPECT_TOKEN('{'); size_t count = cases.size() + 1; @@ -1398,7 +1400,6 @@ AsmType* AsmJsParser::Identifier() { return info->type; } UNREACHABLE(); - return nullptr; } // 6.8.4 CallExpression @@ -1677,7 +1678,7 @@ AsmType* AsmJsParser::MultiplicativeExpression() { } } else if (Check('/')) { AsmType* b; - RECURSEn(b = MultiplicativeExpression()); + RECURSEn(b = UnaryExpression()); if (a->IsA(AsmType::DoubleQ()) && b->IsA(AsmType::DoubleQ())) { current_function_builder_->Emit(kExprF64Div); a = AsmType::Double(); @@ -1695,7 +1696,7 @@ AsmType* AsmJsParser::MultiplicativeExpression() { } } else if (Check('%')) { AsmType* b; - RECURSEn(b = MultiplicativeExpression()); + RECURSEn(b = UnaryExpression()); if (a->IsA(AsmType::DoubleQ()) && b->IsA(AsmType::DoubleQ())) { current_function_builder_->Emit(kExprF64Mod); a = AsmType::Double(); @@ -2014,8 +2015,7 @@ AsmType* AsmJsParser::ValidateCall() { // both cases we might be seeing the {function_name} for the first time and // hence allocate a {VarInfo} here, all subsequent uses of the same name then // need to match the information stored at this point. - // TODO(mstarzinger): Consider using Chromiums base::Optional instead. - std::unique_ptr<TemporaryVariableScope> tmp; + base::Optional<TemporaryVariableScope> tmp; if (Check('[')) { RECURSEn(EqualityExpression()); EXPECT_TOKENn('&'); @@ -2023,7 +2023,7 @@ AsmType* AsmJsParser::ValidateCall() { if (!CheckForUnsigned(&mask)) { FAILn("Expected mask literal"); } - if (!base::bits::IsPowerOfTwo32(mask + 1)) { + if (!base::bits::IsPowerOfTwo(mask + 1)) { FAILn("Expected power of 2 mask"); } current_function_builder_->EmitI32Const(mask); @@ -2050,8 +2050,8 @@ AsmType* AsmJsParser::ValidateCall() { current_function_builder_->EmitI32Const(function_info->index); current_function_builder_->Emit(kExprI32Add); // We have to use a temporary for the correct order of evaluation. - tmp.reset(new TemporaryVariableScope(this)); - current_function_builder_->EmitSetLocal(tmp.get()->get()); + tmp.emplace(this); + current_function_builder_->EmitSetLocal(tmp->get()); // The position of function table calls is after the table lookup. call_pos = static_cast<int>(scanner_.Position()); } else { @@ -2070,8 +2070,8 @@ AsmType* AsmJsParser::ValidateCall() { } // Parse argument list and gather types. - std::vector<AsmType*> param_types; - ZoneVector<AsmType*> param_specific_types(zone()); + CachedVector<AsmType*> param_types(cached_asm_type_p_vectors_); + CachedVector<AsmType*> param_specific_types(cached_asm_type_p_vectors_); EXPECT_TOKENn('('); while (!failed_ && !Peek(')')) { AsmType* t; @@ -2149,10 +2149,12 @@ AsmType* AsmJsParser::ValidateCall() { auto it = function_info->import->cache.find(sig); if (it != function_info->import->cache.end()) { index = it->second; + DCHECK(function_info->function_defined); } else { index = module_builder_->AddImport(function_info->import->function_name, sig); function_info->import->cache[sig] = index; + function_info->function_defined = true; } current_function_builder_->AddAsmWasmOffset(call_pos, to_number_pos); current_function_builder_->EmitWithU32V(kExprCallFunction, index); @@ -2283,7 +2285,7 @@ AsmType* AsmJsParser::ValidateCall() { } } if (function_info->kind == VarKind::kTable) { - current_function_builder_->EmitGetLocal(tmp.get()->get()); + current_function_builder_->EmitGetLocal(tmp->get()); current_function_builder_->AddAsmWasmOffset(call_pos, to_number_pos); current_function_builder_->Emit(kExprCallIndirect); current_function_builder_->EmitU32V(signature_index); @@ -2420,7 +2422,7 @@ void AsmJsParser::ScanToClosingParenthesis() { } } -void AsmJsParser::GatherCases(std::vector<int32_t>* cases) { +void AsmJsParser::GatherCases(ZoneVector<int32_t>* cases) { size_t start = scanner_.Position(); int depth = 0; for (;;) { diff --git a/deps/v8/src/asmjs/asm-parser.h b/deps/v8/src/asmjs/asm-parser.h index 2f20b4813d..4f880785ef 100644 --- a/deps/v8/src/asmjs/asm-parser.h +++ b/deps/v8/src/asmjs/asm-parser.h @@ -5,8 +5,8 @@ #ifndef V8_ASMJS_ASM_PARSER_H_ #define V8_ASMJS_ASM_PARSER_H_ +#include <memory> #include <string> -#include <vector> #include "src/asmjs/asm-scanner.h" #include "src/asmjs/asm-types.h" @@ -15,6 +15,9 @@ namespace v8 { namespace internal { + +class Utf16CharacterStream; + namespace wasm { // A custom parser + validator + wasm converter for asm.js: @@ -46,8 +49,8 @@ class AsmJsParser { typedef std::unordered_set<StandardMember, std::hash<int>> StdlibSet; - explicit AsmJsParser(Isolate* isolate, Zone* zone, Handle<Script> script, - int start, int end); + explicit AsmJsParser(Zone* zone, uintptr_t stack_limit, + std::unique_ptr<Utf16CharacterStream> stream); bool Run(); const char* failure_message() const { return failure_message_; } int failure_location() const { return failure_location_; } @@ -105,6 +108,41 @@ class AsmJsParser { // Helper class to make {TempVariable} safe for nesting. class TemporaryVariableScope; + template <typename T> + class CachedVectors { + public: + explicit CachedVectors(Zone* zone) : reusable_vectors_(zone) {} + + Zone* zone() const { return reusable_vectors_.get_allocator().zone(); } + + inline void fill(ZoneVector<T>* vec) { + if (reusable_vectors_.empty()) return; + reusable_vectors_.back().swap(*vec); + reusable_vectors_.pop_back(); + vec->clear(); + } + + inline void reuse(ZoneVector<T>* vec) { + reusable_vectors_.emplace_back(std::move(*vec)); + } + + private: + ZoneVector<ZoneVector<T>> reusable_vectors_; + }; + + template <typename T> + class CachedVector final : public ZoneVector<T> { + public: + explicit CachedVector(CachedVectors<T>& cache) + : ZoneVector<T>(cache.zone()), cache_(&cache) { + cache.fill(this); + } + ~CachedVector() { cache_->reuse(this); } + + private: + CachedVectors<T>* cache_; + }; + Zone* zone_; AsmJsScanner scanner_; WasmModuleBuilder* module_builder_; @@ -115,6 +153,11 @@ class AsmJsParser { ZoneVector<VarInfo> global_var_info_; ZoneVector<VarInfo> local_var_info_; + CachedVectors<ValueType> cached_valuetype_vectors_{zone_}; + CachedVectors<AsmType*> cached_asm_type_p_vectors_{zone_}; + CachedVectors<AsmJsScanner::token_t> cached_token_t_vectors_{zone_}; + CachedVectors<int32_t> cached_int_vectors_{zone_}; + int function_temp_locals_offset_; int function_temp_locals_used_; int function_temp_locals_depth_; @@ -267,7 +310,7 @@ class AsmJsParser { void InitializeStdlibTypes(); FunctionSig* ConvertSignature(AsmType* return_type, - const std::vector<AsmType*>& params); + const ZoneVector<AsmType*>& params); void ValidateModule(); // 6.1 ValidateModule void ValidateModuleParameters(); // 6.1 ValidateModule - parameters @@ -281,9 +324,9 @@ class AsmJsParser { void ValidateExport(); // 6.2 ValidateExport void ValidateFunctionTable(); // 6.3 ValidateFunctionTable void ValidateFunction(); // 6.4 ValidateFunction - void ValidateFunctionParams(std::vector<AsmType*>* params); + void ValidateFunctionParams(ZoneVector<AsmType*>* params); void ValidateFunctionLocals(size_t param_count, - std::vector<ValueType>* locals); + ZoneVector<ValueType>* locals); void ValidateStatement(); // 6.5 ValidateStatement void Block(); // 6.5.1 Block void ExpressionStatement(); // 6.5.2 ExpressionStatement @@ -331,7 +374,7 @@ class AsmJsParser { // Used as part of {SwitchStatement}. Collects all case labels in the current // switch-statement, then resets the scanner position. This is one piece that // makes this parser not be a pure single-pass. - void GatherCases(std::vector<int32_t>* cases); + void GatherCases(ZoneVector<int32_t>* cases); }; } // namespace wasm diff --git a/deps/v8/src/asmjs/asm-scanner.cc b/deps/v8/src/asmjs/asm-scanner.cc index 14b07306fd..a1e2b05c9d 100644 --- a/deps/v8/src/asmjs/asm-scanner.cc +++ b/deps/v8/src/asmjs/asm-scanner.cc @@ -46,6 +46,10 @@ AsmJsScanner::AsmJsScanner() #undef V } +// Destructor of unique_ptr<T> requires complete declaration of T, we only want +// to include the necessary declaration here instead of the header file. +AsmJsScanner::~AsmJsScanner() {} + void AsmJsScanner::SetStream(std::unique_ptr<Utf16CharacterStream> stream) { stream_ = std::move(stream); Next(); @@ -208,7 +212,6 @@ std::string AsmJsScanner::Name(token_t token) const { break; } UNREACHABLE(); - return "{unreachable}"; } #endif diff --git a/deps/v8/src/asmjs/asm-scanner.h b/deps/v8/src/asmjs/asm-scanner.h index d519862a83..13ffb21bc7 100644 --- a/deps/v8/src/asmjs/asm-scanner.h +++ b/deps/v8/src/asmjs/asm-scanner.h @@ -32,6 +32,8 @@ class V8_EXPORT_PRIVATE AsmJsScanner { typedef int32_t token_t; AsmJsScanner(); + ~AsmJsScanner(); + // Pick the stream to parse (must be called before anything else). void SetStream(std::unique_ptr<Utf16CharacterStream> stream); diff --git a/deps/v8/src/asmjs/asm-types.cc b/deps/v8/src/asmjs/asm-types.cc index 79c43a370b..3deb588e4f 100644 --- a/deps/v8/src/asmjs/asm-types.cc +++ b/deps/v8/src/asmjs/asm-types.cc @@ -69,7 +69,6 @@ bool AsmType::IsA(AsmType* that) { } UNREACHABLE(); - return that == this; } int32_t AsmType::ElementSizeInBytes() { |