diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-02-14 11:27:26 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-02-22 15:55:42 +0100 |
commit | 7a77daf24344db7942e34c962b0f1ee729ab7af5 (patch) | |
tree | e7cbe7bf4e2f4b802a8f5bc18336c546cd6a0d7f /deps/v8/src/runtime | |
parent | 5f08871ee93ea739148cc49e0f7679e33c70295a (diff) | |
download | android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.gz android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.bz2 android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.zip |
deps: update V8 to 5.6.326.55
PR-URL: https://github.com/nodejs/node/pull/10992
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/runtime')
20 files changed, 1249 insertions, 648 deletions
diff --git a/deps/v8/src/runtime/runtime-array.cc b/deps/v8/src/runtime/runtime-array.cc index cbde8f372e..1a2d957caf 100644 --- a/deps/v8/src/runtime/runtime-array.cc +++ b/deps/v8/src/runtime/runtime-array.cc @@ -28,11 +28,13 @@ RUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup) { // This is necessary to enable fast checks for absence of elements // on Array.prototype and below. prototype->set_elements(isolate->heap()->empty_fixed_array()); - return Smi::FromInt(0); + return Smi::kZero; } -static void InstallCode(Isolate* isolate, Handle<JSObject> holder, - const char* name, Handle<Code> code, int argc = -1) { +static void InstallCode( + Isolate* isolate, Handle<JSObject> holder, const char* name, + Handle<Code> code, int argc = -1, + BuiltinFunctionId id = static_cast<BuiltinFunctionId>(-1)) { Handle<String> key = isolate->factory()->InternalizeUtf8String(name); Handle<JSFunction> optimized = isolate->factory()->NewFunctionWithoutPrototype(key, code); @@ -41,15 +43,19 @@ static void InstallCode(Isolate* isolate, Handle<JSObject> holder, } else { optimized->shared()->set_internal_formal_parameter_count(argc); } + if (id >= 0) { + optimized->shared()->set_builtin_function_id(id); + } JSObject::AddProperty(holder, key, optimized, NONE); } -static void InstallBuiltin(Isolate* isolate, Handle<JSObject> holder, - const char* name, Builtins::Name builtin_name, - int argc = -1) { +static void InstallBuiltin( + Isolate* isolate, Handle<JSObject> holder, const char* name, + Builtins::Name builtin_name, int argc = -1, + BuiltinFunctionId id = static_cast<BuiltinFunctionId>(-1)) { InstallCode(isolate, holder, name, - handle(isolate->builtins()->builtin(builtin_name), isolate), - argc); + handle(isolate->builtins()->builtin(builtin_name), isolate), argc, + id); } RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) { @@ -71,6 +77,12 @@ RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) { InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice); InstallBuiltin(isolate, holder, "includes", Builtins::kArrayIncludes, 2); InstallBuiltin(isolate, holder, "indexOf", Builtins::kArrayIndexOf, 2); + InstallBuiltin(isolate, holder, "keys", Builtins::kArrayPrototypeKeys, 0, + kArrayKeys); + InstallBuiltin(isolate, holder, "values", Builtins::kArrayPrototypeValues, 0, + kArrayValues); + InstallBuiltin(isolate, holder, "entries", Builtins::kArrayPrototypeEntries, + 0, kArrayEntries); return *holder; } @@ -140,7 +152,7 @@ RUNTIME_FUNCTION(Runtime_MoveArrayContents) { to->set_length(from->length()); JSObject::ResetElements(from); - from->set_length(Smi::FromInt(0)); + from->set_length(Smi::kZero); JSObject::ValidateElements(to); return *to; @@ -376,7 +388,7 @@ RUNTIME_FUNCTION(Runtime_GrowArrayElements) { if (index >= capacity) { if (!object->GetElementsAccessor()->GrowCapacity(object, index)) { - return Smi::FromInt(0); + return Smi::kZero; } } @@ -423,21 +435,6 @@ RUNTIME_FUNCTION(Runtime_IsArray) { return isolate->heap()->ToBoolean(obj->IsJSArray()); } -RUNTIME_FUNCTION(Runtime_HasCachedArrayIndex) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - return isolate->heap()->false_value(); -} - - -RUNTIME_FUNCTION(Runtime_GetCachedArrayIndex) { - // This can never be reached, because Runtime_HasCachedArrayIndex always - // returns false. - UNIMPLEMENTED(); - return nullptr; -} - - RUNTIME_FUNCTION(Runtime_ArraySpeciesConstructor) { HandleScope scope(isolate); DCHECK(args.length() == 1); @@ -639,5 +636,48 @@ RUNTIME_FUNCTION(Runtime_ArrayIndexOf) { return Smi::FromInt(-1); } +RUNTIME_FUNCTION(Runtime_SpreadIterablePrepare) { + HandleScope scope(isolate); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, spread, 0); + + if (spread->IsJSArray()) { + // Check that the spread arg has fast elements + Handle<JSArray> spread_array = Handle<JSArray>::cast(spread); + ElementsKind array_kind = spread_array->GetElementsKind(); + + // And that it has the orignal ArrayPrototype + JSObject* array_proto = JSObject::cast(spread_array->map()->prototype()); + Map* iterator_map = isolate->initial_array_iterator_prototype()->map(); + + // Check that the iterator acts as expected. + // If IsArrayIteratorLookupChainIntact(), then we know that the initial + // ArrayIterator is being used. If the map of the prototype has changed, + // then take the slow path. + + if (isolate->is_initial_array_prototype(array_proto) && + isolate->IsArrayIteratorLookupChainIntact() && + isolate->is_initial_array_iterator_prototype_map(iterator_map)) { + if (IsFastPackedElementsKind(array_kind)) { + return *spread; + } + if (IsFastHoleyElementsKind(array_kind) && + isolate->IsFastArrayConstructorPrototypeChainIntact()) { + return *spread; + } + } + } + + Handle<JSFunction> spread_iterable_function = isolate->spread_iterable(); + + Handle<Object> spreaded; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, spreaded, + Execution::Call(isolate, spread_iterable_function, + isolate->factory()->undefined_value(), 1, &spread)); + + return *spreaded; +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-collections.cc b/deps/v8/src/runtime/runtime-collections.cc index b25a5ef5c2..57e5d98532 100644 --- a/deps/v8/src/runtime/runtime-collections.cc +++ b/deps/v8/src/runtime/runtime-collections.cc @@ -95,7 +95,7 @@ RUNTIME_FUNCTION(Runtime_SetIteratorInitialize) { kind == JSSetIterator::kKindEntries); Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table())); holder->set_table(*table); - holder->set_index(Smi::FromInt(0)); + holder->set_index(Smi::kZero); holder->set_kind(Smi::FromInt(kind)); return isolate->heap()->undefined_value(); } @@ -191,7 +191,7 @@ RUNTIME_FUNCTION(Runtime_MapIteratorInitialize) { kind == JSMapIterator::kKindEntries); Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table())); holder->set_table(*table); - holder->set_index(Smi::FromInt(0)); + holder->set_index(Smi::kZero); holder->set_kind(Smi::FromInt(kind)); return isolate->heap()->undefined_value(); } diff --git a/deps/v8/src/runtime/runtime-compiler.cc b/deps/v8/src/runtime/runtime-compiler.cc index 01ec73d427..472e076de4 100644 --- a/deps/v8/src/runtime/runtime-compiler.cc +++ b/deps/v8/src/runtime/runtime-compiler.cc @@ -123,7 +123,7 @@ RUNTIME_FUNCTION(Runtime_InstantiateAsmJs) { function->shared()->ReplaceCode( isolate->builtins()->builtin(Builtins::kCompileLazy)); } - return Smi::FromInt(0); + return Smi::kZero; } RUNTIME_FUNCTION(Runtime_NotifyStubFailure) { diff --git a/deps/v8/src/runtime/runtime-debug.cc b/deps/v8/src/runtime/runtime-debug.cc index 2d217b83f7..824ea92a0f 100644 --- a/deps/v8/src/runtime/runtime-debug.cc +++ b/deps/v8/src/runtime/runtime-debug.cc @@ -16,8 +16,8 @@ #include "src/interpreter/interpreter.h" #include "src/isolate-inl.h" #include "src/runtime/runtime.h" -#include "src/wasm/wasm-debug.h" #include "src/wasm/wasm-module.h" +#include "src/wasm/wasm-objects.h" namespace v8 { namespace internal { @@ -47,7 +47,7 @@ RUNTIME_FUNCTION(Runtime_DebugBreakOnBytecode) { isolate->debug()->Break(it.frame()); // If live-edit has dropped frames, we are not going back to dispatch. - if (LiveEdit::SetAfterBreakTarget(isolate->debug())) return Smi::FromInt(0); + if (LiveEdit::SetAfterBreakTarget(isolate->debug())) return Smi::kZero; // Return the handler from the original bytecode array. DCHECK(it.frame()->is_interpreted()); @@ -256,14 +256,14 @@ MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate, const char* status = "rejected"; int status_val = Handle<Smi>::cast(status_obj)->value(); switch (status_val) { - case +1: + case kPromiseFulfilled: status = "resolved"; break; - case 0: + case kPromisePending: status = "pending"; break; default: - DCHECK_EQ(-1, status_val); + DCHECK_EQ(kPromiseRejected, status_val); } Handle<FixedArray> result = factory->NewFixedArray(2 * 2); @@ -457,7 +457,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameCount) { StackFrame::Id id = isolate->debug()->break_frame_id(); if (id == StackFrame::NO_ID) { // If there is no JavaScript stack frame count is 0. - return Smi::FromInt(0); + return Smi::kZero; } for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) { @@ -551,10 +551,10 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { details->set(kFrameDetailsFrameIdIndex, *frame_id); // Add the function name. - Handle<Object> wasm_obj(it.wasm_frame()->wasm_obj(), isolate); + Handle<Object> wasm_instance(it.wasm_frame()->wasm_instance(), isolate); int func_index = it.wasm_frame()->function_index(); Handle<String> func_name = - wasm::GetWasmFunctionName(isolate, wasm_obj, func_index); + wasm::GetWasmFunctionName(isolate, wasm_instance, func_index); details->set(kFrameDetailsFunctionIndex, *func_name); // Add the script wrapper @@ -563,14 +563,26 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { details->set(kFrameDetailsScriptIndex, *script_wrapper); // Add the arguments count. - details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(0)); + details->set(kFrameDetailsArgumentCountIndex, Smi::kZero); // Add the locals count - details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(0)); + details->set(kFrameDetailsLocalCountIndex, Smi::kZero); // Add the source position. + // For wasm, it is function-local, so translate it to a module-relative + // position, such that together with the script it uniquely identifies the + // position. + Handle<Object> positionValue; if (position != kNoSourcePosition) { - details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position)); + int translated_position = position; + if (!wasm::WasmIsAsmJs(*wasm_instance, isolate)) { + Handle<WasmCompiledModule> compiled_module( + wasm::GetCompiledModule(JSObject::cast(*wasm_instance)), isolate); + translated_position += + wasm::GetFunctionCodeOffset(compiled_module, func_index); + } + details->set(kFrameDetailsSourcePositionIndex, + Smi::FromInt(translated_position)); } // Add the constructor information. @@ -929,7 +941,7 @@ RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); - if (!args[0]->IsJSGeneratorObject()) return Smi::FromInt(0); + if (!args[0]->IsJSGeneratorObject()) return Smi::kZero; // Check arguments. CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0); @@ -948,7 +960,7 @@ RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails) { DCHECK(args.length() == 2); if (!args[0]->IsJSGeneratorObject()) { - return *isolate->factory()->undefined_value(); + return isolate->heap()->undefined_value(); } // Check arguments. @@ -1429,6 +1441,7 @@ RUNTIME_FUNCTION(Runtime_DebugGetPrototype) { // Patches script source (should be called upon BeforeCompile event). +// TODO(5530): Remove once uses in debug.js are gone. RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) { HandleScope scope(isolate); DCHECK(args.length() == 2); @@ -1569,6 +1582,7 @@ RUNTIME_FUNCTION(Runtime_GetScript) { return *Script::GetWrapper(found); } +// TODO(5530): Remove once uses in debug.js are gone. RUNTIME_FUNCTION(Runtime_ScriptLineCount) { HandleScope scope(isolate); DCHECK(args.length() == 1); @@ -1583,6 +1597,7 @@ RUNTIME_FUNCTION(Runtime_ScriptLineCount) { return Smi::FromInt(line_ends_array->length()); } +// TODO(5530): Remove once uses in debug.js are gone. RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) { HandleScope scope(isolate); DCHECK(args.length() == 2); @@ -1601,7 +1616,7 @@ RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) { if (line < 0 || line > line_count) { return Smi::FromInt(-1); } else if (line == 0) { - return Smi::FromInt(0); + return Smi::kZero; } else { DCHECK(0 < line && line <= line_count); const int pos = Smi::cast(line_ends_array->get(line - 1))->value() + 1; @@ -1609,6 +1624,7 @@ RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) { } } +// TODO(5530): Remove once uses in debug.js are gone. RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) { HandleScope scope(isolate); DCHECK(args.length() == 2); @@ -1634,7 +1650,7 @@ static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position, Script::OffsetFlag offset_flag, Isolate* isolate) { Script::PositionInfo info; - if (!script->GetPositionInfo(position, &info, offset_flag)) { + if (!Script::GetPositionInfo(script, position, &info, offset_flag)) { return isolate->factory()->null_value(); } @@ -1661,62 +1677,49 @@ static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position, return jsinfo; } -// Get information on a specific source line and column possibly offset by a -// fixed source position. This function is used to find a source position from -// a line and column position. The fixed source position offset is typically -// used to find a source position in a function based on a line and column in -// the source for the function alone. The offset passed will then be the -// start position of the source for the function within the full script source. -// Note that incoming line and column parameters may be undefined, and are -// assumed to be passed *with* offsets. -RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) { - HandleScope scope(isolate); - DCHECK(args.length() == 4); - CONVERT_ARG_CHECKED(JSValue, script, 0); - - CHECK(script->value()->IsScript()); - Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); +namespace { +Handle<Object> ScriptLocationFromLine(Isolate* isolate, Handle<Script> script, + Handle<Object> opt_line, + Handle<Object> opt_column, + int32_t offset) { // Line and column are possibly undefined and we need to handle these cases, // additionally subtracting corresponding offsets. int32_t line; - if (args[1]->IsNull(isolate) || args[1]->IsUndefined(isolate)) { + if (opt_line->IsNull(isolate) || opt_line->IsUndefined(isolate)) { line = 0; } else { - CHECK(args[1]->IsNumber()); - line = NumberToInt32(args[1]) - script_handle->line_offset(); + CHECK(opt_line->IsNumber()); + line = NumberToInt32(*opt_line) - script->line_offset(); } int32_t column; - if (args[2]->IsNull(isolate) || args[2]->IsUndefined(isolate)) { + if (opt_column->IsNull(isolate) || opt_column->IsUndefined(isolate)) { column = 0; } else { - CHECK(args[2]->IsNumber()); - column = NumberToInt32(args[2]); - if (line == 0) column -= script_handle->column_offset(); + CHECK(opt_column->IsNumber()); + column = NumberToInt32(*opt_column); + if (line == 0) column -= script->column_offset(); } - CONVERT_NUMBER_CHECKED(int32_t, offset_position, Int32, args[3]); - - if (line < 0 || column < 0 || offset_position < 0) { - return isolate->heap()->null_value(); + if (line < 0 || column < 0 || offset < 0) { + return isolate->factory()->null_value(); } - Script::InitLineEnds(script_handle); + Script::InitLineEnds(script); - FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends()); + FixedArray* line_ends_array = FixedArray::cast(script->line_ends()); const int line_count = line_ends_array->length(); int position; if (line == 0) { - position = offset_position + column; + position = offset + column; } else { Script::PositionInfo info; - if (!script_handle->GetPositionInfo(offset_position, &info, - Script::NO_OFFSET) || + if (!Script::GetPositionInfo(script, offset, &info, Script::NO_OFFSET) || info.line + line >= line_count) { - return isolate->heap()->null_value(); + return isolate->factory()->null_value(); } const int offset_line = info.line + line; @@ -1727,10 +1730,65 @@ RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) { position = offset_line_position + column; } - return *GetJSPositionInfo(script_handle, position, Script::NO_OFFSET, - isolate); + return GetJSPositionInfo(script, position, Script::NO_OFFSET, isolate); +} + +// Slow traversal over all scripts on the heap. +bool GetScriptById(Isolate* isolate, int needle, Handle<Script>* result) { + Script::Iterator iterator(isolate); + Script* script = NULL; + while ((script = iterator.Next()) != NULL) { + if (script->id() == needle) { + *result = handle(script); + return true; + } + } + + return false; +} + +} // namespace + +// Get information on a specific source line and column possibly offset by a +// fixed source position. This function is used to find a source position from +// a line and column position. The fixed source position offset is typically +// used to find a source position in a function based on a line and column in +// the source for the function alone. The offset passed will then be the +// start position of the source for the function within the full script source. +// Note that incoming line and column parameters may be undefined, and are +// assumed to be passed *with* offsets. +// TODO(5530): Remove once uses in debug.js are gone. +RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) { + HandleScope scope(isolate); + DCHECK(args.length() == 4); + CONVERT_ARG_HANDLE_CHECKED(JSValue, script, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1); + CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2); + CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]); + + CHECK(script->value()->IsScript()); + Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); + + return *ScriptLocationFromLine(isolate, script_handle, opt_line, opt_column, + offset); +} + +// TODO(5530): Rename once conflicting function has been deleted. +RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine2) { + HandleScope scope(isolate); + DCHECK(args.length() == 4); + CONVERT_NUMBER_CHECKED(int32_t, scriptid, Int32, args[0]); + CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1); + CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2); + CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]); + + Handle<Script> script; + CHECK(GetScriptById(isolate, scriptid, &script)); + + return *ScriptLocationFromLine(isolate, script, opt_line, opt_column, offset); } +// TODO(5530): Remove once uses in debug.js are gone. RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) { HandleScope scope(isolate); DCHECK(args.length() == 3); @@ -1748,6 +1806,7 @@ RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) { // Returns the given line as a string, or null if line is out of bounds. // The parameter line is expected to include the script's line offset. +// TODO(5530): Remove once uses in debug.js are gone. RUNTIME_FUNCTION(Runtime_ScriptSourceLine) { HandleScope scope(isolate); DCHECK(args.length() == 2); @@ -1822,12 +1881,19 @@ RUNTIME_FUNCTION(Runtime_DebugPopPromise) { return isolate->heap()->undefined_value(); } +RUNTIME_FUNCTION(Runtime_DebugNextMicrotaskId) { + HandleScope scope(isolate); + DCHECK(args.length() == 0); + return Smi::FromInt(isolate->GetNextDebugMicrotaskId()); +} RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) { - DCHECK(args.length() == 1); + DCHECK(args.length() == 3); HandleScope scope(isolate); - CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0); - isolate->debug()->OnAsyncTaskEvent(data); + CONVERT_ARG_HANDLE_CHECKED(String, type, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, id, 1); + CONVERT_ARG_HANDLE_CHECKED(String, name, 2); + isolate->debug()->OnAsyncTaskEvent(type, id, name); return isolate->heap()->undefined_value(); } @@ -1843,34 +1909,5 @@ RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) { return NULL; } -RUNTIME_FUNCTION(Runtime_GetWasmFunctionOffsetTable) { - DCHECK(args.length() == 1); - HandleScope scope(isolate); - CONVERT_ARG_CHECKED(JSValue, script_val, 0); - - CHECK(script_val->value()->IsScript()); - Handle<Script> script = Handle<Script>(Script::cast(script_val->value())); - - Handle<wasm::WasmDebugInfo> debug_info = - wasm::GetDebugInfo(handle(script->wasm_object(), isolate)); - Handle<FixedArray> elements = wasm::WasmDebugInfo::GetFunctionOffsetTable( - debug_info, script->wasm_function_index()); - return *isolate->factory()->NewJSArrayWithElements(elements); -} - -RUNTIME_FUNCTION(Runtime_DisassembleWasmFunction) { - DCHECK(args.length() == 1); - HandleScope scope(isolate); - CONVERT_ARG_CHECKED(JSValue, script_val, 0); - - CHECK(script_val->value()->IsScript()); - Handle<Script> script = Handle<Script>(Script::cast(script_val->value())); - - Handle<wasm::WasmDebugInfo> debug_info = - wasm::GetDebugInfo(handle(script->wasm_object(), isolate)); - return *wasm::WasmDebugInfo::DisassembleFunction( - debug_info, script->wasm_function_index()); -} - } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-function.cc b/deps/v8/src/runtime/runtime-function.cc index fa50941925..a91ab28cc6 100644 --- a/deps/v8/src/runtime/runtime-function.cc +++ b/deps/v8/src/runtime/runtime-function.cc @@ -55,7 +55,7 @@ RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) { return isolate->heap()->undefined_value(); } - +// TODO(5530): Remove once uses in debug.js are gone. RUNTIME_FUNCTION(Runtime_FunctionGetScript) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); @@ -71,6 +71,20 @@ RUNTIME_FUNCTION(Runtime_FunctionGetScript) { return isolate->heap()->undefined_value(); } +RUNTIME_FUNCTION(Runtime_FunctionGetScriptId) { + HandleScope scope(isolate); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); + + if (function->IsJSFunction()) { + Handle<Object> script( + Handle<JSFunction>::cast(function)->shared()->script(), isolate); + if (script->IsScript()) { + return Smi::FromInt(Handle<Script>::cast(script)->id()); + } + } + return Smi::FromInt(-1); +} RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) { HandleScope scope(isolate); diff --git a/deps/v8/src/runtime/runtime-i18n.cc b/deps/v8/src/runtime/runtime-i18n.cc index cac403baca..75e0952581 100644 --- a/deps/v8/src/runtime/runtime-i18n.cc +++ b/deps/v8/src/runtime/runtime-i18n.cc @@ -926,7 +926,7 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) { if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) { return *isolate->factory()->NewStringFromStaticChars("none"); } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) { - return *isolate->factory()->number_string(); + return isolate->heap()->number_string(); } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) { return *isolate->factory()->NewStringFromStaticChars("letter"); } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) { @@ -939,55 +939,10 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) { } namespace { -void ConvertCaseWithTransliterator(icu::UnicodeString* input, - const char* transliterator_id) { - UErrorCode status = U_ZERO_ERROR; - std::unique_ptr<icu::Transliterator> translit( - icu::Transliterator::createInstance( - icu::UnicodeString(transliterator_id, -1, US_INV), UTRANS_FORWARD, - status)); - if (U_FAILURE(status)) return; - translit->transliterate(*input); -} - MUST_USE_RESULT Object* LocaleConvertCase(Handle<String> s, Isolate* isolate, bool is_to_upper, const char* lang) { - int32_t src_length = s->length(); - - // Greek uppercasing has to be done via transliteration. - // TODO(jshin): Drop this special-casing once ICU's regular case conversion - // API supports Greek uppercasing. See - // http://bugs.icu-project.org/trac/ticket/10582 . - // In the meantime, if there's no Greek character in |s|, call this - // function again with the root locale (lang=""). - // ICU's C API for transliteration is nasty and we just use C++ API. - if (V8_UNLIKELY(is_to_upper && lang[0] == 'e' && lang[1] == 'l')) { - icu::UnicodeString converted; - std::unique_ptr<uc16[]> sap; - { - DisallowHeapAllocation no_gc; - String::FlatContent flat = s->GetFlatContent(); - const UChar* src = GetUCharBufferFromFlat(flat, &sap, src_length); - // Starts with the source string (read-only alias with copy-on-write - // semantics) and will be modified to contain the converted result. - // Using read-only alias at first saves one copy operation if - // transliteration does not change the input, which is rather rare. - // Moreover, transliteration takes rather long so that saving one copy - // helps only a little bit. - converted.setTo(false, src, src_length); - ConvertCaseWithTransliterator(&converted, "el-Upper"); - // If no change is made, just return |s|. - if (converted.getBuffer() == src) return *s; - } - RETURN_RESULT_OR_FAILURE( - isolate, - isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>( - reinterpret_cast<const uint16_t*>(converted.getBuffer()), - converted.length()))); - } - auto case_converter = is_to_upper ? u_strToUpper : u_strToLower; - + int32_t src_length = s->length(); int32_t dest_length = src_length; UErrorCode status; Handle<SeqTwoByteString> result; @@ -1138,7 +1093,7 @@ RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) { s = String::Flatten(s); // First scan the string for uppercase and non-ASCII characters: if (s->HasOnlyOneByteChars()) { - unsigned first_index_to_lower = length; + int first_index_to_lower = length; for (int index = 0; index < length; ++index) { // Blink specializes this path for one-byte strings, so it // does not need to do a generic get, but can do the equivalent @@ -1165,14 +1120,16 @@ RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) { String::FlatContent flat = s->GetFlatContent(); if (flat.IsOneByte()) { const uint8_t* src = flat.ToOneByteVector().start(); - CopyChars(result->GetChars(), src, first_index_to_lower); + CopyChars(result->GetChars(), src, + static_cast<size_t>(first_index_to_lower)); for (int index = first_index_to_lower; index < length; ++index) { uint16_t ch = static_cast<uint16_t>(src[index]); result->SeqOneByteStringSet(index, ToLatin1Lower(ch)); } } else { const uint16_t* src = flat.ToUC16Vector().start(); - CopyChars(result->GetChars(), src, first_index_to_lower); + CopyChars(result->GetChars(), src, + static_cast<size_t>(first_index_to_lower)); for (int index = first_index_to_lower; index < length; ++index) { uint16_t ch = src[index]; result->SeqOneByteStringSet(index, ToLatin1Lower(ch)); @@ -1283,7 +1240,7 @@ RUNTIME_FUNCTION(Runtime_DateCacheVersion) { if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) { Handle<FixedArray> date_cache_version = isolate->factory()->NewFixedArray(1, TENURED); - date_cache_version->set(0, Smi::FromInt(0)); + date_cache_version->set(0, Smi::kZero); isolate->eternal_handles()->CreateSingleton( isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION); } diff --git a/deps/v8/src/runtime/runtime-internal.cc b/deps/v8/src/runtime/runtime-internal.cc index 26882b5c83..621f33547e 100644 --- a/deps/v8/src/runtime/runtime-internal.cc +++ b/deps/v8/src/runtime/runtime-internal.cc @@ -100,12 +100,29 @@ RUNTIME_FUNCTION(Runtime_ThrowStackOverflow) { return isolate->StackOverflow(); } +RUNTIME_FUNCTION(Runtime_ThrowTypeError) { + HandleScope scope(isolate); + DCHECK_LE(1, args.length()); + CONVERT_SMI_ARG_CHECKED(message_id_smi, 0); + + Handle<Object> undefined = isolate->factory()->undefined_value(); + Handle<Object> arg0 = (args.length() > 1) ? args.at<Object>(1) : undefined; + Handle<Object> arg1 = (args.length() > 2) ? args.at<Object>(2) : undefined; + Handle<Object> arg2 = (args.length() > 3) ? args.at<Object>(3) : undefined; + + MessageTemplate::Template message_id = + static_cast<MessageTemplate::Template>(message_id_smi); + + THROW_NEW_ERROR_RETURN_FAILURE(isolate, + NewTypeError(message_id, arg0, arg1, arg2)); +} + RUNTIME_FUNCTION(Runtime_ThrowWasmError) { HandleScope scope(isolate); DCHECK_EQ(2, args.length()); CONVERT_SMI_ARG_CHECKED(message_id, 0); CONVERT_SMI_ARG_CHECKED(byte_offset, 1); - Handle<Object> error_obj = isolate->factory()->NewError( + Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError( static_cast<MessageTemplate::Template>(message_id)); // For wasm traps, the byte offset (a.k.a source position) can not be @@ -270,64 +287,6 @@ RUNTIME_FUNCTION(Runtime_ThrowApplyNonFunction) { isolate, NewTypeError(MessageTemplate::kApplyNonFunction, object, type)); } -namespace { - -void PromiseRejectEvent(Isolate* isolate, Handle<JSObject> promise, - Handle<Object> rejected_promise, Handle<Object> value, - bool debug_event) { - if (isolate->debug()->is_active() && debug_event) { - isolate->debug()->OnPromiseReject(rejected_promise, value); - } - Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol(); - // Do not report if we actually have a handler. - if (JSReceiver::GetDataProperty(promise, key)->IsUndefined(isolate)) { - isolate->ReportPromiseReject(promise, value, - v8::kPromiseRejectWithNoHandler); - } -} - -} // namespace - -RUNTIME_FUNCTION(Runtime_PromiseRejectEvent) { - DCHECK(args.length() == 3); - HandleScope scope(isolate); - CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); - CONVERT_BOOLEAN_ARG_CHECKED(debug_event, 2); - - PromiseRejectEvent(isolate, promise, promise, value, debug_event); - return isolate->heap()->undefined_value(); -} - -RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) { - DCHECK(args.length() == 2); - HandleScope scope(isolate); - CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); - - Handle<Object> rejected_promise = promise; - if (isolate->debug()->is_active()) { - // If the Promise.reject call is caught, then this will return - // undefined, which will be interpreted by PromiseRejectEvent - // as being a caught exception event. - rejected_promise = isolate->GetPromiseOnStackOnThrow(); - } - PromiseRejectEvent(isolate, promise, rejected_promise, value, true); - return isolate->heap()->undefined_value(); -} - -RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) { - DCHECK(args.length() == 1); - HandleScope scope(isolate); - CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); - Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol(); - // At this point, no revocation has been issued before - CHECK(JSReceiver::GetDataProperty(promise, key)->IsUndefined(isolate)); - isolate->ReportPromiseReject(promise, Handle<Object>(), - v8::kPromiseHandlerAddedAfterReject); - return isolate->heap()->undefined_value(); -} - RUNTIME_FUNCTION(Runtime_StackGuard) { SealHandleScope shs(isolate); @@ -430,10 +389,10 @@ bool ComputeLocation(Isolate* isolate, MessageLocation* target) { Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object) { MessageLocation location; if (ComputeLocation(isolate, &location)) { - Zone zone(isolate->allocator()); + Zone zone(isolate->allocator(), ZONE_NAME); std::unique_ptr<ParseInfo> info( location.function()->shared()->is_function() - ? new ParseInfo(&zone, location.function()) + ? new ParseInfo(&zone, handle(location.function()->shared())) : new ParseInfo(&zone, location.script())); if (Parser::ParseStatic(info.get())) { CallPrinter printer(isolate, location.function()->shared()->IsBuiltin()); @@ -554,36 +513,6 @@ RUNTIME_FUNCTION(Runtime_GetAndResetRuntimeCallStats) { } } -RUNTIME_FUNCTION(Runtime_EnqueuePromiseResolveThenableJob) { - HandleScope scope(isolate); - DCHECK(args.length() == 6); - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, resolution, 0); - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, then, 1); - CONVERT_ARG_HANDLE_CHECKED(JSFunction, resolve, 2); - CONVERT_ARG_HANDLE_CHECKED(JSFunction, reject, 3); - CONVERT_ARG_HANDLE_CHECKED(Object, before_debug_event, 4); - CONVERT_ARG_HANDLE_CHECKED(Object, after_debug_event, 5); - Handle<PromiseContainer> container = isolate->factory()->NewPromiseContainer( - resolution, then, resolve, reject, before_debug_event, after_debug_event); - isolate->EnqueueMicrotask(container); - return isolate->heap()->undefined_value(); -} - -RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSFunction, microtask, 0); - isolate->EnqueueMicrotask(microtask); - return isolate->heap()->undefined_value(); -} - -RUNTIME_FUNCTION(Runtime_RunMicrotasks) { - HandleScope scope(isolate); - DCHECK(args.length() == 0); - isolate->RunMicrotasks(); - return isolate->heap()->undefined_value(); -} - RUNTIME_FUNCTION(Runtime_OrdinaryHasInstance) { HandleScope scope(isolate); DCHECK_EQ(2, args.length()); @@ -593,13 +522,13 @@ RUNTIME_FUNCTION(Runtime_OrdinaryHasInstance) { isolate, Object::OrdinaryHasInstance(isolate, callable, object)); } -RUNTIME_FUNCTION(Runtime_IsWasmObject) { +RUNTIME_FUNCTION(Runtime_IsWasmInstance) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); CONVERT_ARG_CHECKED(Object, object, 0); - bool is_wasm_object = - object->IsJSObject() && wasm::IsWasmObject(JSObject::cast(object)); - return *isolate->factory()->ToBoolean(is_wasm_object); + bool is_wasm_instance = + object->IsJSObject() && wasm::IsWasmInstance(JSObject::cast(object)); + return *isolate->factory()->ToBoolean(is_wasm_instance); } RUNTIME_FUNCTION(Runtime_Typeof) { diff --git a/deps/v8/src/runtime/runtime-interpreter.cc b/deps/v8/src/runtime/runtime-interpreter.cc index ce71e2c52d..62eee1744f 100644 --- a/deps/v8/src/runtime/runtime-interpreter.cc +++ b/deps/v8/src/runtime/runtime-interpreter.cc @@ -171,5 +171,19 @@ RUNTIME_FUNCTION(Runtime_InterpreterSetPendingMessage) { return isolate->heap()->undefined_value(); } +RUNTIME_FUNCTION(Runtime_InterpreterAdvanceBytecodeOffset) { + SealHandleScope shs(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0); + CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1); + interpreter::BytecodeArrayIterator it(bytecode_array); + int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag; + while (it.current_offset() < offset) it.Advance(); + DCHECK_EQ(offset, it.current_offset()); + it.Advance(); // Advance by one bytecode. + offset = it.current_offset() + BytecodeArray::kHeaderSize - kHeapObjectTag; + return Smi::FromInt(offset); +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-literals.cc b/deps/v8/src/runtime/runtime-literals.cc index ebdf04ccae..8bb4522a98 100644 --- a/deps/v8/src/runtime/runtime-literals.cc +++ b/deps/v8/src/runtime/runtime-literals.cc @@ -86,7 +86,7 @@ MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate( if (key->ToArrayIndex(&element_index)) { // Array index (uint32). if (value->IsUninitialized(isolate)) { - value = handle(Smi::FromInt(0), isolate); + value = handle(Smi::kZero, isolate); } maybe_result = JSObject::SetOwnElementIgnoreAttributes( boilerplate, element_index, value, NONE); diff --git a/deps/v8/src/runtime/runtime-maths.cc b/deps/v8/src/runtime/runtime-maths.cc index 47e560d022..404305a150 100644 --- a/deps/v8/src/runtime/runtime-maths.cc +++ b/deps/v8/src/runtime/runtime-maths.cc @@ -15,58 +15,49 @@ namespace internal { RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) { HandleScope scope(isolate); - DCHECK(args.length() == 1); - if (isolate->serializer_enabled()) { - // Random numbers in the snapshot are not really that random. And we cannot - // return a typed array as it cannot be serialized. To make calling - // Math.random possible when creating a custom startup snapshot, we simply - // return a normal array with a single random number. - Handle<HeapNumber> random_number = isolate->factory()->NewHeapNumber( - isolate->random_number_generator()->NextDouble()); - Handle<FixedArray> array_backing = isolate->factory()->NewFixedArray(1); - array_backing->set(0, *random_number); - return *isolate->factory()->NewJSArrayWithElements(array_backing); - } + DCHECK(args.length() == 0); + + Handle<Context> native_context = isolate->native_context(); + DCHECK_EQ(0, native_context->math_random_index()->value()); + + static const int kCacheSize = 64; + static const int kState0Offset = kCacheSize - 1; + static const int kState1Offset = kState0Offset - 1; + // The index is decremented before used to access the cache. + static const int kInitialIndex = kState1Offset; - static const int kState0Offset = 0; - static const int kState1Offset = 1; - static const int kRandomBatchSize = 64; - CONVERT_ARG_HANDLE_CHECKED(Object, maybe_typed_array, 0); - Handle<JSTypedArray> typed_array; - // Allocate typed array if it does not yet exist. - if (maybe_typed_array->IsJSTypedArray()) { - typed_array = Handle<JSTypedArray>::cast(maybe_typed_array); + Handle<FixedDoubleArray> cache; + uint64_t state0 = 0; + uint64_t state1 = 0; + if (native_context->math_random_cache()->IsFixedDoubleArray()) { + cache = Handle<FixedDoubleArray>( + FixedDoubleArray::cast(native_context->math_random_cache()), isolate); + state0 = double_to_uint64(cache->get_scalar(kState0Offset)); + state1 = double_to_uint64(cache->get_scalar(kState1Offset)); } else { - static const int kByteLength = kRandomBatchSize * kDoubleSize; - Handle<JSArrayBuffer> buffer = - isolate->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, TENURED); - JSArrayBuffer::SetupAllocatingData(buffer, isolate, kByteLength, true, - SharedFlag::kNotShared); - typed_array = isolate->factory()->NewJSTypedArray( - kExternalFloat64Array, buffer, 0, kRandomBatchSize); + cache = Handle<FixedDoubleArray>::cast( + isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED)); + native_context->set_math_random_cache(*cache); + // Initialize state if not yet initialized. + while (state0 == 0 || state1 == 0) { + isolate->random_number_generator()->NextBytes(&state0, sizeof(state0)); + isolate->random_number_generator()->NextBytes(&state1, sizeof(state1)); + } } DisallowHeapAllocation no_gc; - double* array = - reinterpret_cast<double*>(typed_array->GetBuffer()->backing_store()); - // Fetch existing state. - uint64_t state0 = double_to_uint64(array[kState0Offset]); - uint64_t state1 = double_to_uint64(array[kState1Offset]); - // Initialize state if not yet initialized. - while (state0 == 0 || state1 == 0) { - isolate->random_number_generator()->NextBytes(&state0, sizeof(state0)); - isolate->random_number_generator()->NextBytes(&state1, sizeof(state1)); - } + FixedDoubleArray* raw_cache = *cache; // Create random numbers. - for (int i = kState1Offset + 1; i < kRandomBatchSize; i++) { + for (int i = 0; i < kInitialIndex; i++) { // Generate random numbers using xorshift128+. base::RandomNumberGenerator::XorShift128(&state0, &state1); - array[i] = base::RandomNumberGenerator::ToDouble(state0, state1); + raw_cache->set(i, base::RandomNumberGenerator::ToDouble(state0, state1)); } + // Persist current state. - array[kState0Offset] = uint64_to_double(state0); - array[kState1Offset] = uint64_to_double(state1); - return *typed_array; + raw_cache->set(kState0Offset, uint64_to_double(state0)); + raw_cache->set(kState1Offset, uint64_to_double(state1)); + return Smi::FromInt(kInitialIndex); } } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-module.cc b/deps/v8/src/runtime/runtime-module.cc new file mode 100644 index 0000000000..2b813430e0 --- /dev/null +++ b/deps/v8/src/runtime/runtime-module.cc @@ -0,0 +1,39 @@ +// 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 "src/runtime/runtime-utils.h" + +#include "src/arguments.h" + +namespace v8 { +namespace internal { + +RUNTIME_FUNCTION(Runtime_GetModuleNamespace) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + CONVERT_SMI_ARG_CHECKED(module_request, 0); + Handle<Module> module(isolate->context()->module()); + return *Module::GetModuleNamespace(module, module_request); +} + +RUNTIME_FUNCTION(Runtime_LoadModuleVariable) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + CONVERT_SMI_ARG_CHECKED(index, 0); + Handle<Module> module(isolate->context()->module()); + return *Module::LoadVariable(module, index); +} + +RUNTIME_FUNCTION(Runtime_StoreModuleVariable) { + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_SMI_ARG_CHECKED(index, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); + Handle<Module> module(isolate->context()->module()); + Module::StoreVariable(module, index, value); + return isolate->heap()->undefined_value(); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/runtime/runtime-numbers.cc b/deps/v8/src/runtime/runtime-numbers.cc index 9f43c0acfc..bfe8763e99 100644 --- a/deps/v8/src/runtime/runtime-numbers.cc +++ b/deps/v8/src/runtime/runtime-numbers.cc @@ -33,28 +33,40 @@ RUNTIME_FUNCTION(Runtime_StringToNumber) { // ES6 18.2.5 parseInt(string, radix) slow path RUNTIME_FUNCTION(Runtime_StringParseInt) { HandleScope handle_scope(isolate); - DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); - CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]); - // Step 8.a. is already handled in the JS function. - CHECK(radix == 0 || (2 <= radix && radix <= 36)); - + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, string, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, radix, 1); + + // Convert {string} to a String first, and flatten it. + Handle<String> subject; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, subject, + Object::ToString(isolate, string)); subject = String::Flatten(subject); - double value; + // Convert {radix} to Int32. + if (!radix->IsNumber()) { + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix, Object::ToNumber(radix)); + } + int radix32 = DoubleToInt32(radix->Number()); + if (radix32 != 0 && (radix32 < 2 || radix32 > 36)) { + return isolate->heap()->nan_value(); + } + + double result; { DisallowHeapAllocation no_gc; String::FlatContent flat = subject->GetFlatContent(); if (flat.IsOneByte()) { - value = - StringToInt(isolate->unicode_cache(), flat.ToOneByteVector(), radix); + result = StringToInt(isolate->unicode_cache(), flat.ToOneByteVector(), + radix32); } else { - value = StringToInt(isolate->unicode_cache(), flat.ToUC16Vector(), radix); + result = + StringToInt(isolate->unicode_cache(), flat.ToUC16Vector(), radix32); } } - return *isolate->factory()->NewNumber(value); + return *isolate->factory()->NewNumber(result); } diff --git a/deps/v8/src/runtime/runtime-object.cc b/deps/v8/src/runtime/runtime-object.cc index 70ed23ba61..c7e9cf3c92 100644 --- a/deps/v8/src/runtime/runtime-object.cc +++ b/deps/v8/src/runtime/runtime-object.cc @@ -207,6 +207,70 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) { return isolate->heap()->false_value(); } +// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] ) +// TODO(verwaest): Support the common cases with precached map directly in +// an Object.create stub. +RUNTIME_FUNCTION(Runtime_ObjectCreate) { + HandleScope scope(isolate); + Handle<Object> prototype = args.at<Object>(0); + if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype)); + } + + // Generate the map with the specified {prototype} based on the Object + // function's initial map from the current native context. + // TODO(bmeurer): Use a dedicated cache for Object.create; think about + // slack tracking for Object.create. + Handle<Map> map(isolate->native_context()->object_function()->initial_map(), + isolate); + if (map->prototype() != *prototype) { + if (prototype->IsNull(isolate)) { + map = isolate->slow_object_with_null_prototype_map(); + } else if (prototype->IsJSObject()) { + Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype); + if (!js_prototype->map()->is_prototype_map()) { + JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE); + } + Handle<PrototypeInfo> info = + Map::GetOrCreatePrototypeInfo(js_prototype, isolate); + // TODO(verwaest): Use inobject slack tracking for this map. + if (info->HasObjectCreateMap()) { + map = handle(info->ObjectCreateMap(), isolate); + } else { + map = Map::CopyInitialMap(map); + Map::SetPrototype(map, prototype, FAST_PROTOTYPE); + PrototypeInfo::SetObjectCreateMap(info, map); + } + } else { + map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE); + } + } + + bool is_dictionary_map = map->is_dictionary_map(); + Handle<FixedArray> object_properties; + if (is_dictionary_map) { + // Allocate the actual properties dictionay up front to avoid invalid object + // state. + object_properties = + NameDictionary::New(isolate, NameDictionary::kInitialCapacity); + } + // Actually allocate the object. + Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map); + if (is_dictionary_map) { + object->set_properties(*object_properties); + } + + // Define the properties if properties was specified and is not undefined. + Handle<Object> properties = args.at<Object>(1); + if (!properties->IsUndefined(isolate)) { + RETURN_FAILURE_ON_EXCEPTION( + isolate, JSReceiver::DefineProperties(isolate, object, properties)); + } + + return *object; +} + MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate, Handle<Object> object, Handle<Object> key, @@ -250,18 +314,6 @@ RUNTIME_FUNCTION(Runtime_InternalSetPrototype) { return *obj; } - -RUNTIME_FUNCTION(Runtime_SetPrototype) { - HandleScope scope(isolate); - DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); - MAYBE_RETURN( - JSReceiver::SetPrototype(obj, prototype, true, Object::THROW_ON_ERROR), - isolate->heap()->exception()); - return *obj; -} - RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) { HandleScope scope(isolate); DCHECK(args.length() == 2); @@ -277,64 +329,6 @@ RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) { } -namespace { - -Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value, - LanguageMode language_mode) { - // Go up context chain to the script context. - Handle<Context> script_context(isolate->context()->script_context(), isolate); - DCHECK(script_context->IsScriptContext()); - DCHECK(script_context->get(slot)->IsPropertyCell()); - - // Lookup the named property on the global object. - Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate); - Handle<Name> name(scope_info->ContextSlotName(slot), isolate); - Handle<JSGlobalObject> global_object(script_context->global_object(), - isolate); - LookupIterator it(global_object, name, global_object, LookupIterator::OWN); - - // Switch to fast mode only if there is a data property and it's not on - // a hidden prototype. - if (it.state() == LookupIterator::DATA && - it.GetHolder<Object>().is_identical_to(global_object)) { - // Now update cell in the script context. - Handle<PropertyCell> cell = it.GetPropertyCell(); - script_context->set(slot, *cell); - } else { - // This is not a fast case, so keep this access in a slow mode. - // Store empty_property_cell here to release the outdated property cell. - script_context->set(slot, isolate->heap()->empty_property_cell()); - } - - MAYBE_RETURN(Object::SetProperty(&it, value, language_mode, - Object::CERTAINLY_NOT_STORE_FROM_KEYED), - isolate->heap()->exception()); - return *value; -} - -} // namespace - - -RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Sloppy) { - HandleScope scope(isolate); - DCHECK_EQ(2, args.length()); - CONVERT_SMI_ARG_CHECKED(slot, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); - - return StoreGlobalViaContext(isolate, slot, value, SLOPPY); -} - - -RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Strict) { - HandleScope scope(isolate); - DCHECK_EQ(2, args.length()); - CONVERT_SMI_ARG_CHECKED(slot, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); - - return StoreGlobalViaContext(isolate, slot, value, STRICT); -} - - RUNTIME_FUNCTION(Runtime_GetProperty) { HandleScope scope(isolate); DCHECK(args.length() == 2); @@ -530,7 +524,7 @@ RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) { HandleScope scope(isolate); DCHECK(args.length() == 1); if (!args[0]->IsJSObject()) { - return Smi::FromInt(0); + return Smi::kZero; } CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); @@ -604,14 +598,14 @@ RUNTIME_FUNCTION(Runtime_TryMigrateInstance) { HandleScope scope(isolate); DCHECK(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); - if (!object->IsJSObject()) return Smi::FromInt(0); + if (!object->IsJSObject()) return Smi::kZero; Handle<JSObject> js_object = Handle<JSObject>::cast(object); - if (!js_object->map()->is_deprecated()) return Smi::FromInt(0); + if (!js_object->map()->is_deprecated()) return Smi::kZero; // This call must not cause lazy deopts, because it's called from deferred // code where we can't handle lazy deopts for lack of a suitable bailout // ID. So we just try migration and signal failure if necessary, // which will also trigger a deopt. - if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0); + if (!JSObject::TryMigrateInstance(js_object)) return Smi::kZero; return *object; } @@ -928,13 +922,20 @@ RUNTIME_FUNCTION(Runtime_CreateIterResultObject) { DCHECK_EQ(2, args.length()); CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); CONVERT_ARG_HANDLE_CHECKED(Object, done, 1); - Handle<JSObject> result = - isolate->factory()->NewJSObjectFromMap(isolate->iterator_result_map()); - result->InObjectPropertyAtPut(JSIteratorResult::kValueIndex, *value); - result->InObjectPropertyAtPut(JSIteratorResult::kDoneIndex, *done); - return *result; + return *isolate->factory()->NewJSIteratorResult(value, done->BooleanValue()); } +RUNTIME_FUNCTION(Runtime_CreateKeyValueArray) { + HandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, key, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); + Handle<FixedArray> elements = isolate->factory()->NewFixedArray(2); + elements->set(0, *key); + elements->set(1, *value); + return *isolate->factory()->NewJSArrayWithElements(elements, FAST_ELEMENTS, + 2); +} RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) { SealHandleScope shs(isolate); @@ -960,32 +961,6 @@ RUNTIME_FUNCTION(Runtime_CreateDataProperty) { return *value; } -RUNTIME_FUNCTION(Runtime_LoadModuleExport) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(String, name, 0); - Handle<Module> module(isolate->context()->module()); - return *Module::LoadExport(module, name); -} - -RUNTIME_FUNCTION(Runtime_LoadModuleImport) { - HandleScope scope(isolate); - DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(String, name, 0); - CONVERT_ARG_HANDLE_CHECKED(Smi, module_request, 1); - Handle<Module> module(isolate->context()->module()); - return *Module::LoadImport(module, name, module_request->value()); -} - -RUNTIME_FUNCTION(Runtime_StoreModuleExport) { - HandleScope scope(isolate); - DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(String, name, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); - Handle<Module> module(isolate->context()->module()); - Module::StoreExport(module, name, value); - return isolate->heap()->undefined_value(); -} } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-promise.cc b/deps/v8/src/runtime/runtime-promise.cc new file mode 100644 index 0000000000..226993a50e --- /dev/null +++ b/deps/v8/src/runtime/runtime-promise.cc @@ -0,0 +1,193 @@ +// 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 "src/runtime/runtime-utils.h" + +#include "src/debug/debug.h" +#include "src/elements.h" +#include "src/promise-utils.h" + +namespace v8 { +namespace internal { + +namespace { + +void PromiseRejectEvent(Isolate* isolate, Handle<JSReceiver> promise, + Handle<Object> rejected_promise, Handle<Object> value, + bool debug_event) { + if (isolate->debug()->is_active() && debug_event) { + isolate->debug()->OnPromiseReject(rejected_promise, value); + } + Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol(); + // Do not report if we actually have a handler. + if (JSReceiver::GetDataProperty(promise, key)->IsUndefined(isolate)) { + isolate->ReportPromiseReject(Handle<JSObject>::cast(promise), value, + v8::kPromiseRejectWithNoHandler); + } +} + +} // namespace + +RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) { + DCHECK(args.length() == 2); + HandleScope scope(isolate); + CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); + + Handle<Object> rejected_promise = promise; + if (isolate->debug()->is_active()) { + // If the Promise.reject call is caught, then this will return + // undefined, which will be interpreted by PromiseRejectEvent + // as being a caught exception event. + rejected_promise = isolate->GetPromiseOnStackOnThrow(); + } + PromiseRejectEvent(isolate, promise, rejected_promise, value, true); + return isolate->heap()->undefined_value(); +} + +RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) { + DCHECK(args.length() == 1); + HandleScope scope(isolate); + CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); + Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol(); + // At this point, no revocation has been issued before + CHECK(JSReceiver::GetDataProperty(promise, key)->IsUndefined(isolate)); + isolate->ReportPromiseReject(promise, Handle<Object>(), + v8::kPromiseHandlerAddedAfterReject); + return isolate->heap()->undefined_value(); +} + +namespace { +void EnqueuePromiseReactionJob(Isolate* isolate, Handle<Object> value, + Handle<Object> tasks, Handle<Object> deferred, + Handle<Object> status) { + Handle<Object> debug_id = isolate->factory()->undefined_value(); + Handle<Object> debug_name = isolate->factory()->undefined_value(); + if (isolate->debug()->is_active()) { + MaybeHandle<Object> maybe_result; + Handle<Object> argv[] = {deferred, status}; + maybe_result = Execution::TryCall( + isolate, isolate->promise_debug_get_info(), + isolate->factory()->undefined_value(), arraysize(argv), argv); + Handle<Object> result; + if ((maybe_result).ToHandle(&result)) { + CHECK(result->IsJSArray()); + Handle<JSArray> array = Handle<JSArray>::cast(result); + ElementsAccessor* accessor = array->GetElementsAccessor(); + DCHECK(accessor->HasElement(array, 0)); + DCHECK(accessor->HasElement(array, 1)); + debug_id = accessor->Get(array, 0); + debug_name = accessor->Get(array, 1); + } + } + Handle<PromiseReactionJobInfo> info = + isolate->factory()->NewPromiseReactionJobInfo(value, tasks, deferred, + debug_id, debug_name, + isolate->native_context()); + isolate->EnqueueMicrotask(info); +} + +void PromiseFulfill(Isolate* isolate, Handle<JSReceiver> promise, + Handle<Smi> status, Handle<Object> value, + Handle<Symbol> reaction) { + Handle<Object> tasks = JSReceiver::GetDataProperty(promise, reaction); + if (!tasks->IsUndefined(isolate)) { + Handle<Object> deferred = JSReceiver::GetDataProperty( + promise, isolate->factory()->promise_deferred_reaction_symbol()); + EnqueuePromiseReactionJob(isolate, value, tasks, deferred, status); + } +} +} // namespace + +RUNTIME_FUNCTION(Runtime_PromiseReject) { + DCHECK(args.length() == 3); + HandleScope scope(isolate); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, promise, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1); + CONVERT_BOOLEAN_ARG_CHECKED(debug_event, 2); + + PromiseRejectEvent(isolate, promise, promise, reason, debug_event); + + Handle<Smi> status = handle(Smi::FromInt(kPromiseRejected), isolate); + Handle<Symbol> reaction = + isolate->factory()->promise_reject_reactions_symbol(); + PromiseFulfill(isolate, promise, status, reason, reaction); + return isolate->heap()->undefined_value(); +} + +RUNTIME_FUNCTION(Runtime_PromiseFulfill) { + DCHECK(args.length() == 4); + HandleScope scope(isolate); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, promise, 0); + CONVERT_ARG_HANDLE_CHECKED(Smi, status, 1); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); + CONVERT_ARG_HANDLE_CHECKED(Symbol, reaction, 3); + PromiseFulfill(isolate, promise, status, value, reaction); + return isolate->heap()->undefined_value(); +} + +RUNTIME_FUNCTION(Runtime_EnqueuePromiseReactionJob) { + HandleScope scope(isolate); + DCHECK(args.length() == 4); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, tasks, 1); + CONVERT_ARG_HANDLE_CHECKED(Object, deferred, 2); + CONVERT_ARG_HANDLE_CHECKED(Object, status, 3); + EnqueuePromiseReactionJob(isolate, value, tasks, deferred, status); + return isolate->heap()->undefined_value(); +} + +RUNTIME_FUNCTION(Runtime_EnqueuePromiseResolveThenableJob) { + HandleScope scope(isolate); + DCHECK(args.length() == 3); + CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, resolution, 1); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, then, 2); + + // TODO(gsathya): Add fast path for native promises with unmodified + // PromiseThen (which don't need these resolving functions, but + // instead can just call resolve/reject directly). + Handle<JSFunction> resolve, reject; + PromiseUtils::CreateResolvingFunctions( + isolate, promise, isolate->factory()->false_value(), &resolve, &reject); + + Handle<Object> debug_id, debug_name; + if (isolate->debug()->is_active()) { + debug_id = + handle(Smi::FromInt(isolate->GetNextDebugMicrotaskId()), isolate); + debug_name = isolate->factory()->PromiseResolveThenableJob_string(); + isolate->debug()->OnAsyncTaskEvent(isolate->factory()->enqueue_string(), + debug_id, + Handle<String>::cast(debug_name)); + } else { + debug_id = isolate->factory()->undefined_value(); + debug_name = isolate->factory()->undefined_value(); + } + + Handle<PromiseResolveThenableJobInfo> info = + isolate->factory()->NewPromiseResolveThenableJobInfo( + resolution, then, resolve, reject, debug_id, debug_name, + isolate->native_context()); + isolate->EnqueueMicrotask(info); + + return isolate->heap()->undefined_value(); +} + +RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, microtask, 0); + isolate->EnqueueMicrotask(microtask); + return isolate->heap()->undefined_value(); +} + +RUNTIME_FUNCTION(Runtime_RunMicrotasks) { + HandleScope scope(isolate); + DCHECK(args.length() == 0); + isolate->RunMicrotasks(); + return isolate->heap()->undefined_value(); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/runtime/runtime-regexp.cc b/deps/v8/src/runtime/runtime-regexp.cc index 977e6bc48f..d572eedd31 100644 --- a/deps/v8/src/runtime/runtime-regexp.cc +++ b/deps/v8/src/runtime/runtime-regexp.cc @@ -10,6 +10,7 @@ #include "src/messages.h" #include "src/regexp/jsregexp-inl.h" #include "src/regexp/jsregexp.h" +#include "src/regexp/regexp-utils.h" #include "src/string-builder.h" #include "src/string-search.h" @@ -279,10 +280,8 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder, } } - void FindOneByteStringIndices(Vector<const uint8_t> subject, uint8_t pattern, - ZoneList<int>* indices, unsigned int limit, - Zone* zone) { + List<int>* indices, unsigned int limit) { DCHECK(limit > 0); // Collect indices of pattern in subject using memchr. // Stop after finding at most limit values. @@ -293,32 +292,29 @@ void FindOneByteStringIndices(Vector<const uint8_t> subject, uint8_t pattern, pos = reinterpret_cast<const uint8_t*>( memchr(pos, pattern, subject_end - pos)); if (pos == NULL) return; - indices->Add(static_cast<int>(pos - subject_start), zone); + indices->Add(static_cast<int>(pos - subject_start)); pos++; limit--; } } - void FindTwoByteStringIndices(const Vector<const uc16> subject, uc16 pattern, - ZoneList<int>* indices, unsigned int limit, - Zone* zone) { + List<int>* indices, unsigned int limit) { DCHECK(limit > 0); const uc16* subject_start = subject.start(); const uc16* subject_end = subject_start + subject.length(); for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) { if (*pos == pattern) { - indices->Add(static_cast<int>(pos - subject_start), zone); + indices->Add(static_cast<int>(pos - subject_start)); limit--; } } } - template <typename SubjectChar, typename PatternChar> void FindStringIndices(Isolate* isolate, Vector<const SubjectChar> subject, - Vector<const PatternChar> pattern, - ZoneList<int>* indices, unsigned int limit, Zone* zone) { + Vector<const PatternChar> pattern, List<int>* indices, + unsigned int limit) { DCHECK(limit > 0); // Collect indices of pattern in subject. // Stop after finding at most limit values. @@ -328,16 +324,15 @@ void FindStringIndices(Isolate* isolate, Vector<const SubjectChar> subject, while (limit > 0) { index = search.Search(subject, index); if (index < 0) return; - indices->Add(index, zone); + indices->Add(index); index += pattern_length; limit--; } } - void FindStringIndicesDispatch(Isolate* isolate, String* subject, - String* pattern, ZoneList<int>* indices, - unsigned int limit, Zone* zone) { + String* pattern, List<int>* indices, + unsigned int limit) { { DisallowHeapAllocation no_gc; String::FlatContent subject_content = subject->GetFlatContent(); @@ -351,14 +346,14 @@ void FindStringIndicesDispatch(Isolate* isolate, String* subject, pattern_content.ToOneByteVector(); if (pattern_vector.length() == 1) { FindOneByteStringIndices(subject_vector, pattern_vector[0], indices, - limit, zone); + limit); } else { FindStringIndices(isolate, subject_vector, pattern_vector, indices, - limit, zone); + limit); } } else { FindStringIndices(isolate, subject_vector, - pattern_content.ToUC16Vector(), indices, limit, zone); + pattern_content.ToUC16Vector(), indices, limit); } } else { Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); @@ -367,34 +362,51 @@ void FindStringIndicesDispatch(Isolate* isolate, String* subject, pattern_content.ToOneByteVector(); if (pattern_vector.length() == 1) { FindTwoByteStringIndices(subject_vector, pattern_vector[0], indices, - limit, zone); + limit); } else { FindStringIndices(isolate, subject_vector, pattern_vector, indices, - limit, zone); + limit); } } else { Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector(); if (pattern_vector.length() == 1) { FindTwoByteStringIndices(subject_vector, pattern_vector[0], indices, - limit, zone); + limit); } else { FindStringIndices(isolate, subject_vector, pattern_vector, indices, - limit, zone); + limit); } } } } } +namespace { +List<int>* GetRewoundRegexpIndicesList(Isolate* isolate) { + List<int>* list = isolate->regexp_indices(); + list->Rewind(0); + return list; +} + +void TruncateRegexpIndicesList(Isolate* isolate) { + // Same size as smallest zone segment, preserving behavior from the + // runtime zone. + static const int kMaxRegexpIndicesListCapacity = 8 * KB; + if (isolate->regexp_indices()->capacity() > kMaxRegexpIndicesListCapacity) { + isolate->regexp_indices()->Clear(); // Throw away backing storage + } +} +} // namespace + template <typename ResultSeqString> MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString( Isolate* isolate, Handle<String> subject, Handle<JSRegExp> pattern_regexp, - Handle<String> replacement, Handle<JSObject> last_match_info) { + Handle<String> replacement, Handle<RegExpMatchInfo> last_match_info) { DCHECK(subject->IsFlat()); DCHECK(replacement->IsFlat()); - ZoneScope zone_scope(isolate->runtime_zone()); - ZoneList<int> indices(8, zone_scope.zone()); + List<int>* indices = GetRewoundRegexpIndicesList(isolate); + DCHECK_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag()); String* pattern = String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex)); @@ -402,10 +414,9 @@ MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString( int pattern_len = pattern->length(); int replacement_len = replacement->length(); - FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff, - zone_scope.zone()); + FindStringIndicesDispatch(isolate, *subject, pattern, indices, 0xffffffff); - int matches = indices.length(); + int matches = indices->length(); if (matches == 0) return *subject; // Detect integer overflow. @@ -436,10 +447,10 @@ MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString( for (int i = 0; i < matches; i++) { // Copy non-matched subject content. - if (subject_pos < indices.at(i)) { + if (subject_pos < indices->at(i)) { String::WriteToFlat(*subject, result->GetChars() + result_pos, - subject_pos, indices.at(i)); - result_pos += indices.at(i) - subject_pos; + subject_pos, indices->at(i)); + result_pos += indices->at(i) - subject_pos; } // Replace match. @@ -449,7 +460,7 @@ MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString( result_pos += replacement_len; } - subject_pos = indices.at(i) + pattern_len; + subject_pos = indices->at(i) + pattern_len; } // Add remaining subject content at the end. if (subject_pos < subject_len) { @@ -457,16 +468,18 @@ MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString( subject_len); } - int32_t match_indices[] = {indices.at(matches - 1), - indices.at(matches - 1) + pattern_len}; + int32_t match_indices[] = {indices->at(matches - 1), + indices->at(matches - 1) + pattern_len}; RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices); + TruncateRegexpIndicesList(isolate); + return *result; } MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString( Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, - Handle<String> replacement, Handle<JSObject> last_match_info) { + Handle<String> replacement, Handle<RegExpMatchInfo> last_match_info) { DCHECK(subject->IsFlat()); DCHECK(replacement->IsFlat()); @@ -474,8 +487,8 @@ MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString( int subject_length = subject->length(); // CompiledReplacement uses zone allocation. - ZoneScope zone_scope(isolate->runtime_zone()); - CompiledReplacement compiled_replacement(zone_scope.zone()); + Zone zone(isolate->allocator(), ZONE_NAME); + CompiledReplacement compiled_replacement(&zone); bool simple_replace = compiled_replacement.Compile(replacement, capture_count, subject_length); @@ -548,7 +561,7 @@ MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString( template <typename ResultSeqString> MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString( Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, - Handle<JSObject> last_match_info) { + Handle<RegExpMatchInfo> last_match_info) { DCHECK(subject->IsFlat()); // Shortcut for simple non-regexp global replacements @@ -643,18 +656,12 @@ MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString( return *answer; } +namespace { -RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) { - HandleScope scope(isolate); - DCHECK(args.length() == 4); - - CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); - CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2); - CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, last_match_info, 3); - +Object* StringReplaceGlobalRegExpWithStringHelper( + Isolate* isolate, Handle<JSRegExp> regexp, Handle<String> subject, + Handle<String> replacement, Handle<RegExpMatchInfo> last_match_info) { CHECK(regexp->GetFlags() & JSRegExp::kGlobal); - CHECK(last_match_info->HasFastObjectElements()); subject = String::Flatten(subject); @@ -674,6 +681,20 @@ RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) { replacement, last_match_info); } +} // namespace + +RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) { + HandleScope scope(isolate); + DCHECK(args.length() == 4); + + CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); + CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2); + CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); + CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 3); + + return StringReplaceGlobalRegExpWithStringHelper( + isolate, regexp, subject, replacement, last_match_info); +} RUNTIME_FUNCTION(Runtime_StringSplit) { HandleScope handle_scope(isolate); @@ -694,7 +715,7 @@ RUNTIME_FUNCTION(Runtime_StringSplit) { &last_match_cache_unused, RegExpResultsCache::STRING_SPLIT_SUBSTRINGS), isolate); - if (*cached_answer != Smi::FromInt(0)) { + if (*cached_answer != Smi::kZero) { // The cache FixedArray is a COW-array and can therefore be reused. Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements( Handle<FixedArray>::cast(cached_answer)); @@ -709,25 +730,18 @@ RUNTIME_FUNCTION(Runtime_StringSplit) { subject = String::Flatten(subject); pattern = String::Flatten(pattern); - static const int kMaxInitialListCapacity = 16; + List<int>* indices = GetRewoundRegexpIndicesList(isolate); - ZoneScope zone_scope(isolate->runtime_zone()); + FindStringIndicesDispatch(isolate, *subject, *pattern, indices, limit); - // Find (up to limit) indices of separator and end-of-string in subject - int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit); - ZoneList<int> indices(initial_capacity, zone_scope.zone()); - - FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit, - zone_scope.zone()); - - if (static_cast<uint32_t>(indices.length()) < limit) { - indices.Add(subject_length, zone_scope.zone()); + if (static_cast<uint32_t>(indices->length()) < limit) { + indices->Add(subject_length); } // The list indices now contains the end of each part to create. // Create JSArray of substrings separated by separator. - int part_count = indices.length(); + int part_count = indices->length(); Handle<JSArray> result = isolate->factory()->NewJSArray(FAST_ELEMENTS, part_count, part_count, @@ -737,12 +751,12 @@ RUNTIME_FUNCTION(Runtime_StringSplit) { Handle<FixedArray> elements(FixedArray::cast(result->elements())); - if (part_count == 1 && indices.at(0) == subject_length) { + if (part_count == 1 && indices->at(0) == subject_length) { elements->set(0, *subject); } else { int part_start = 0; FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < part_count, i++, { - int part_end = indices.at(i); + int part_end = indices->at(i); Handle<String> substring = isolate->factory()->NewProperSubString(subject, part_start, part_end); elements->set(i, *substring); @@ -758,9 +772,37 @@ RUNTIME_FUNCTION(Runtime_StringSplit) { } } + TruncateRegexpIndicesList(isolate); + return *result; } +// ES##sec-regexpcreate +// RegExpCreate ( P, F ) +RUNTIME_FUNCTION(Runtime_RegExpCreate) { + HandleScope scope(isolate); + DCHECK(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(Object, source_object, 0); + + Handle<String> source; + if (source_object->IsUndefined(isolate)) { + source = isolate->factory()->empty_string(); + } else { + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, source, Object::ToString(isolate, source_object)); + } + + Handle<Map> map(isolate->regexp_function()->initial_map()); + Handle<JSRegExp> regexp = + Handle<JSRegExp>::cast(isolate->factory()->NewJSObjectFromMap(map)); + + JSRegExp::Flags flags = JSRegExp::kNone; + + RETURN_FAILURE_ON_EXCEPTION(isolate, + JSRegExp::Initialize(regexp, source, flags)); + + return *regexp; +} RUNTIME_FUNCTION(Runtime_RegExpExec) { HandleScope scope(isolate); @@ -768,7 +810,7 @@ RUNTIME_FUNCTION(Runtime_RegExpExec) { CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); CONVERT_INT32_ARG_CHECKED(index, 2); - CONVERT_ARG_HANDLE_CHECKED(JSObject, last_match_info, 3); + CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 3); // Due to the way the JS calls are constructed this must be less than the // length of a string, i.e. it is always a Smi. We check anyway for security. CHECK(index >= 0); @@ -778,64 +820,116 @@ RUNTIME_FUNCTION(Runtime_RegExpExec) { isolate, RegExpImpl::Exec(regexp, subject, index, last_match_info)); } +RUNTIME_FUNCTION(Runtime_RegExpInternalReplace) { + HandleScope scope(isolate); + DCHECK(args.length() == 3); + CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); + CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); + CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2); -RUNTIME_FUNCTION(Runtime_RegExpFlags) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); - return regexp->flags(); + Handle<RegExpMatchInfo> internal_match_info = + isolate->regexp_internal_match_info(); + + return StringReplaceGlobalRegExpWithStringHelper( + isolate, regexp, subject, replacement, internal_match_info); } +namespace { -RUNTIME_FUNCTION(Runtime_RegExpSource) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); - return regexp->source(); -} +class MatchInfoBackedMatch : public String::Match { + public: + MatchInfoBackedMatch(Isolate* isolate, Handle<String> subject, + Handle<RegExpMatchInfo> match_info) + : isolate_(isolate), match_info_(match_info) { + subject_ = String::Flatten(subject); + } -// TODO(jgruber): Remove this once all uses in regexp.js have been removed. -RUNTIME_FUNCTION(Runtime_RegExpConstructResult) { - HandleScope handle_scope(isolate); - DCHECK(args.length() == 3); - CONVERT_SMI_ARG_CHECKED(size, 0); - CHECK(size >= 0 && size <= FixedArray::kMaxLength); - CONVERT_ARG_HANDLE_CHECKED(Object, index, 1); - CONVERT_ARG_HANDLE_CHECKED(Object, input, 2); - Handle<FixedArray> elements = isolate->factory()->NewFixedArray(size); - Handle<Map> regexp_map(isolate->native_context()->regexp_result_map()); - Handle<JSObject> object = - isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED); - Handle<JSArray> array = Handle<JSArray>::cast(object); - array->set_elements(*elements); - array->set_length(Smi::FromInt(size)); - // Write in-object properties after the length of the array. - array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, *index); - array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, *input); - return *array; -} + Handle<String> GetMatch() override { + return RegExpUtils::GenericCaptureGetter(isolate_, match_info_, 0, nullptr); + } + MaybeHandle<String> GetCapture(int i, bool* capture_exists) override { + Handle<Object> capture_obj = RegExpUtils::GenericCaptureGetter( + isolate_, match_info_, i, capture_exists); + return (*capture_exists) ? Object::ToString(isolate_, capture_obj) + : isolate_->factory()->empty_string(); + } -RUNTIME_FUNCTION(Runtime_RegExpInitializeAndCompile) { - HandleScope scope(isolate); - DCHECK(args.length() == 3); - CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); - CONVERT_ARG_HANDLE_CHECKED(String, source, 1); - CONVERT_ARG_HANDLE_CHECKED(String, flags, 2); + Handle<String> GetPrefix() override { + const int match_start = match_info_->Capture(0); + return isolate_->factory()->NewSubString(subject_, 0, match_start); + } - RETURN_FAILURE_ON_EXCEPTION(isolate, - JSRegExp::Initialize(regexp, source, flags)); + Handle<String> GetSuffix() override { + const int match_end = match_info_->Capture(1); + return isolate_->factory()->NewSubString(subject_, match_end, + subject_->length()); + } - return *regexp; -} + int CaptureCount() override { + return match_info_->NumberOfCaptureRegisters() / 2; + } + + virtual ~MatchInfoBackedMatch() {} + + private: + Isolate* isolate_; + Handle<String> subject_; + Handle<RegExpMatchInfo> match_info_; +}; + +class VectorBackedMatch : public String::Match { + public: + VectorBackedMatch(Isolate* isolate, Handle<String> subject, + Handle<String> match, int match_position, + ZoneVector<Handle<Object>>* captures) + : isolate_(isolate), + match_(match), + match_position_(match_position), + captures_(captures) { + subject_ = String::Flatten(subject); + } + + Handle<String> GetMatch() override { return match_; } + + MaybeHandle<String> GetCapture(int i, bool* capture_exists) override { + Handle<Object> capture_obj = captures_->at(i); + if (capture_obj->IsUndefined(isolate_)) { + *capture_exists = false; + return isolate_->factory()->empty_string(); + } + *capture_exists = true; + return Object::ToString(isolate_, capture_obj); + } + Handle<String> GetPrefix() override { + return isolate_->factory()->NewSubString(subject_, 0, match_position_); + } + + Handle<String> GetSuffix() override { + const int match_end_position = match_position_ + match_->length(); + return isolate_->factory()->NewSubString(subject_, match_end_position, + subject_->length()); + } + + int CaptureCount() override { return static_cast<int>(captures_->size()); } + + virtual ~VectorBackedMatch() {} + + private: + Isolate* isolate_; + Handle<String> subject_; + Handle<String> match_; + const int match_position_; + ZoneVector<Handle<Object>>* captures_; +}; // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain // separate last match info. See comment on that function. template <bool has_capture> static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, - Handle<JSObject> last_match_array, + Handle<RegExpMatchInfo> last_match_array, Handle<JSArray> result_array) { DCHECK(subject->IsFlat()); DCHECK_NE(has_capture, regexp->CaptureCount() == 0); @@ -858,8 +952,11 @@ static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject, } Handle<FixedArray> cached_fixed_array = Handle<FixedArray>(FixedArray::cast(cached_answer)); - // The cache FixedArray is a COW-array and can therefore be reused. - JSArray::SetContent(result_array, cached_fixed_array); + // The cache FixedArray is a COW-array and we need to return a copy. + Handle<FixedArray> copied_fixed_array = + isolate->factory()->CopyFixedArrayWithMap( + cached_fixed_array, isolate->factory()->fixed_array_map()); + JSArray::SetContent(result_array, copied_fixed_array); RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count, last_match); DeleteArray(last_match); @@ -964,9 +1061,12 @@ static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject, } Handle<FixedArray> result_fixed_array = builder.array(); result_fixed_array->Shrink(builder.length()); - // Cache the result and turn the FixedArray into a COW array. + // Cache the result and copy the FixedArray into a COW array. + Handle<FixedArray> copied_fixed_array = + isolate->factory()->CopyFixedArrayWithMap( + result_fixed_array, isolate->factory()->fixed_array_map()); RegExpResultsCache::Enter( - isolate, subject, handle(regexp->data(), isolate), result_fixed_array, + isolate, subject, handle(regexp->data(), isolate), copied_fixed_array, last_match_cache, RegExpResultsCache::REGEXP_MULTIPLE_INDICES); } return *builder.ToJSArray(result_array); @@ -975,19 +1075,174 @@ static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject, } } +MUST_USE_RESULT MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction( + Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, + Handle<Object> replace_obj) { + Factory* factory = isolate->factory(); + Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info(); + + // TODO(jgruber): This is a pattern we could refactor. + Handle<Object> match_indices_obj; + ASSIGN_RETURN_ON_EXCEPTION( + isolate, match_indices_obj, + RegExpImpl::Exec(regexp, subject, 0, last_match_info), String); + + if (match_indices_obj->IsNull(isolate)) { + RETURN_ON_EXCEPTION(isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0), + String); + return subject; + } + + Handle<RegExpMatchInfo> match_indices = + Handle<RegExpMatchInfo>::cast(match_indices_obj); + + const int index = match_indices->Capture(0); + const int end_of_match = match_indices->Capture(1); + + IncrementalStringBuilder builder(isolate); + builder.AppendString(factory->NewSubString(subject, 0, index)); + + // Compute the parameter list consisting of the match, captures, index, + // and subject for the replace function invocation. + // The number of captures plus one for the match. + const int m = match_indices->NumberOfCaptureRegisters() / 2; + + const int argc = m + 2; + ScopedVector<Handle<Object>> argv(argc); + + for (int j = 0; j < m; j++) { + bool ok; + Handle<String> capture = + RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok); + if (ok) { + argv[j] = capture; + } else { + argv[j] = factory->undefined_value(); + } + } + + argv[argc - 2] = handle(Smi::FromInt(index), isolate); + argv[argc - 1] = subject; + + Handle<Object> replacement_obj; + ASSIGN_RETURN_ON_EXCEPTION( + isolate, replacement_obj, + Execution::Call(isolate, replace_obj, factory->undefined_value(), argc, + argv.start()), + String); + + Handle<String> replacement; + ASSIGN_RETURN_ON_EXCEPTION( + isolate, replacement, Object::ToString(isolate, replacement_obj), String); + + builder.AppendString(replacement); + builder.AppendString( + factory->NewSubString(subject, end_of_match, subject->length())); + + return builder.Finish(); +} + +// Legacy implementation of RegExp.prototype[Symbol.replace] which +// doesn't properly call the underlying exec method. +MUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate, + Handle<JSRegExp> regexp, + Handle<String> string, + Handle<Object> replace_obj) { + Factory* factory = isolate->factory(); + + // TODO(jgruber): We need the even stricter guarantee of an unmodified + // JSRegExp map here for access to GetFlags to be legal. + const int flags = regexp->GetFlags(); + const bool global = (flags & JSRegExp::kGlobal) != 0; + + // Functional fast-paths are dispatched directly by replace builtin. + DCHECK(!replace_obj->IsCallable()); + + Handle<String> replace; + ASSIGN_RETURN_ON_EXCEPTION(isolate, replace, + Object::ToString(isolate, replace_obj), String); + replace = String::Flatten(replace); + + Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info(); + + if (!global) { + // Non-global regexp search, string replace. + + Handle<Object> match_indices_obj; + ASSIGN_RETURN_ON_EXCEPTION( + isolate, match_indices_obj, + RegExpImpl::Exec(regexp, string, 0, last_match_info), String); + + if (match_indices_obj->IsNull(isolate)) { + RETURN_ON_EXCEPTION( + isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0), String); + return string; + } + + auto match_indices = Handle<RegExpMatchInfo>::cast(match_indices_obj); -// This is only called for StringReplaceGlobalRegExpWithFunction. This sets -// lastMatchInfoOverride to maintain the last match info, so we don't need to -// set any other last match array info. + const int start_index = match_indices->Capture(0); + const int end_index = match_indices->Capture(1); + + IncrementalStringBuilder builder(isolate); + builder.AppendString(factory->NewSubString(string, 0, start_index)); + + if (replace->length() > 0) { + MatchInfoBackedMatch m(isolate, string, match_indices); + Handle<String> replacement; + ASSIGN_RETURN_ON_EXCEPTION(isolate, replacement, + String::GetSubstitution(isolate, &m, replace), + String); + builder.AppendString(replacement); + } + + builder.AppendString( + factory->NewSubString(string, end_index, string->length())); + return builder.Finish(); + } else { + // Global regexp search, string replace. + DCHECK(global); + RETURN_ON_EXCEPTION(isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0), + String); + + if (replace->length() == 0) { + if (string->HasOnlyOneByteChars()) { + Object* result = + StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>( + isolate, string, regexp, last_match_info); + return handle(String::cast(result), isolate); + } else { + Object* result = + StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>( + isolate, string, regexp, last_match_info); + return handle(String::cast(result), isolate); + } + } + + Object* result = StringReplaceGlobalRegExpWithString( + isolate, string, regexp, replace, last_match_info); + if (result->IsString()) { + return handle(String::cast(result), isolate); + } else { + return MaybeHandle<String>(); + } + } + + UNREACHABLE(); + return MaybeHandle<String>(); +} + +} // namespace + +// This is only called for StringReplaceGlobalRegExpWithFunction. RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) { HandleScope handles(isolate); DCHECK(args.length() == 4); CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, last_match_info, 2); + CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 2); CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3); - CHECK(last_match_info->HasFastObjectElements()); CHECK(result_array->HasFastObjectElements()); subject = String::Flatten(subject); @@ -1002,6 +1257,188 @@ RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) { } } +RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) { + HandleScope scope(isolate); + DCHECK(args.length() == 3); + + CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); + CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); + CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2); + + RETURN_RESULT_OR_FAILURE(isolate, StringReplaceNonGlobalRegExpWithFunction( + isolate, subject, regexp, replace)); +} + +// Slow path for: +// ES#sec-regexp.prototype-@@replace +// RegExp.prototype [ @@replace ] ( string, replaceValue ) +RUNTIME_FUNCTION(Runtime_RegExpReplace) { + HandleScope scope(isolate); + DCHECK(args.length() == 3); + + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, recv, 0); + CONVERT_ARG_HANDLE_CHECKED(String, string, 1); + Handle<Object> replace_obj = args.at<Object>(2); + + Factory* factory = isolate->factory(); + + string = String::Flatten(string); + + // Fast-path for unmodified JSRegExps. + if (RegExpUtils::IsUnmodifiedRegExp(isolate, recv)) { + RETURN_RESULT_OR_FAILURE( + isolate, RegExpReplace(isolate, Handle<JSRegExp>::cast(recv), string, + replace_obj)); + } + + const int length = string->length(); + const bool functional_replace = replace_obj->IsCallable(); + + Handle<String> replace; + if (!functional_replace) { + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, replace, + Object::ToString(isolate, replace_obj)); + } + + Handle<Object> global_obj; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, global_obj, + JSReceiver::GetProperty(recv, factory->global_string())); + const bool global = global_obj->BooleanValue(); + + bool unicode = false; + if (global) { + Handle<Object> unicode_obj; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, unicode_obj, + JSReceiver::GetProperty(recv, factory->unicode_string())); + unicode = unicode_obj->BooleanValue(); + + RETURN_FAILURE_ON_EXCEPTION(isolate, + RegExpUtils::SetLastIndex(isolate, recv, 0)); + } + + Zone zone(isolate->allocator(), ZONE_NAME); + ZoneVector<Handle<Object>> results(&zone); + + while (true) { + Handle<Object> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, RegExpUtils::RegExpExec(isolate, recv, string, + factory->undefined_value())); + + if (result->IsNull(isolate)) break; + + results.push_back(result); + if (!global) break; + + Handle<Object> match_obj; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match_obj, + Object::GetElement(isolate, result, 0)); + + Handle<String> match; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match, + Object::ToString(isolate, match_obj)); + + if (match->length() == 0) { + RETURN_FAILURE_ON_EXCEPTION(isolate, RegExpUtils::SetAdvancedStringIndex( + isolate, recv, string, unicode)); + } + } + + // TODO(jgruber): Look into ReplacementStringBuilder instead. + IncrementalStringBuilder builder(isolate); + int next_source_position = 0; + + for (const auto& result : results) { + Handle<Object> captures_length_obj; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, captures_length_obj, + Object::GetProperty(result, factory->length_string())); + + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, captures_length_obj, + Object::ToLength(isolate, captures_length_obj)); + const int captures_length = + std::max(Handle<Smi>::cast(captures_length_obj)->value(), 0); + + Handle<Object> match_obj; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match_obj, + Object::GetElement(isolate, result, 0)); + + Handle<String> match; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match, + Object::ToString(isolate, match_obj)); + + const int match_length = match->length(); + + Handle<Object> position_obj; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, position_obj, + Object::GetProperty(result, factory->index_string())); + + // TODO(jgruber): Extract and correct error handling. Since we can go up to + // 2^53 - 1 (at least for ToLength), we might actually need uint64_t here? + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, position_obj, Object::ToInteger(isolate, position_obj)); + const int position = + std::max(std::min(Handle<Smi>::cast(position_obj)->value(), length), 0); + + ZoneVector<Handle<Object>> captures(&zone); + for (int n = 0; n < captures_length; n++) { + Handle<Object> capture; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, capture, Object::GetElement(isolate, result, n)); + + if (!capture->IsUndefined(isolate)) { + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, capture, + Object::ToString(isolate, capture)); + } + captures.push_back(capture); + } + + Handle<String> replacement; + if (functional_replace) { + const int argc = captures_length + 2; + ScopedVector<Handle<Object>> argv(argc); + + for (int j = 0; j < captures_length; j++) { + argv[j] = captures[j]; + } + + argv[captures_length] = handle(Smi::FromInt(position), isolate); + argv[captures_length + 1] = string; + + Handle<Object> replacement_obj; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, replacement_obj, + Execution::Call(isolate, replace_obj, factory->undefined_value(), + argc, argv.start())); + + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, replacement, Object::ToString(isolate, replacement_obj)); + } else { + VectorBackedMatch m(isolate, string, match, position, &captures); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, replacement, String::GetSubstitution(isolate, &m, replace)); + } + + if (position >= next_source_position) { + builder.AppendString( + factory->NewSubString(string, next_source_position, position)); + builder.AppendString(replacement); + + next_source_position = position + match_length; + } + } + + if (next_source_position < length) { + builder.AppendString( + factory->NewSubString(string, next_source_position, length)); + } + + RETURN_RESULT_OR_FAILURE(isolate, builder.Finish()); +} RUNTIME_FUNCTION(Runtime_RegExpExecReThrow) { SealHandleScope shs(isolate); @@ -1018,5 +1455,6 @@ RUNTIME_FUNCTION(Runtime_IsRegExp) { CONVERT_ARG_CHECKED(Object, obj, 0); return isolate->heap()->ToBoolean(obj->IsJSRegExp()); } + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-scopes.cc b/deps/v8/src/runtime/runtime-scopes.cc index 0c037db307..377799fe04 100644 --- a/deps/v8/src/runtime/runtime-scopes.cc +++ b/deps/v8/src/runtime/runtime-scopes.cc @@ -903,7 +903,7 @@ MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value, // The property was found in a context slot. if (index != Context::kNotFound) { if (flag == kNeedsInitialization && - Handle<Context>::cast(holder)->is_the_hole(index)) { + Handle<Context>::cast(holder)->is_the_hole(isolate, index)) { THROW_NEW_ERROR(isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object); diff --git a/deps/v8/src/runtime/runtime-strings.cc b/deps/v8/src/runtime/runtime-strings.cc index f5bda59b26..328bdceb37 100644 --- a/deps/v8/src/runtime/runtime-strings.cc +++ b/deps/v8/src/runtime/runtime-strings.cc @@ -90,17 +90,8 @@ RUNTIME_FUNCTION(Runtime_StringReplaceOneCharWithString) { RUNTIME_FUNCTION(Runtime_StringIndexOf) { HandleScope scope(isolate); DCHECK(args.length() == 3); - - CONVERT_ARG_HANDLE_CHECKED(String, sub, 0); - CONVERT_ARG_HANDLE_CHECKED(String, pat, 1); - CONVERT_ARG_HANDLE_CHECKED(Object, index, 2); - - uint32_t start_index = 0; - if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1); - - CHECK(start_index <= static_cast<uint32_t>(sub->length())); - int position = String::IndexOf(isolate, sub, pat, start_index); - return Smi::FromInt(position); + return String::IndexOf(isolate, args.at<Object>(0), args.at<Object>(1), + args.at<Object>(2)); } RUNTIME_FUNCTION(Runtime_StringLastIndexOf) { @@ -166,59 +157,6 @@ RUNTIME_FUNCTION(Runtime_InternalizeString) { } -RUNTIME_FUNCTION(Runtime_StringMatch) { - HandleScope handles(isolate); - DCHECK(args.length() == 3); - - CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); - CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); - CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2); - - CHECK(regexp_info->HasFastObjectElements()); - - RegExpImpl::GlobalCache global_cache(regexp, subject, isolate); - if (global_cache.HasException()) return isolate->heap()->exception(); - - int capture_count = regexp->CaptureCount(); - - ZoneScope zone_scope(isolate->runtime_zone()); - ZoneList<int> offsets(8, zone_scope.zone()); - - while (true) { - int32_t* match = global_cache.FetchNext(); - if (match == NULL) break; - offsets.Add(match[0], zone_scope.zone()); // start - offsets.Add(match[1], zone_scope.zone()); // end - } - - if (global_cache.HasException()) return isolate->heap()->exception(); - - if (offsets.length() == 0) { - // Not a single match. - return isolate->heap()->null_value(); - } - - RegExpImpl::SetLastMatchInfo(regexp_info, subject, capture_count, - global_cache.LastSuccessfulMatch()); - - int matches = offsets.length() / 2; - Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches); - Handle<String> substring = - isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1)); - elements->set(0, *substring); - FOR_WITH_HANDLE_SCOPE(isolate, int, i = 1, i, i < matches, i++, { - int from = offsets.at(i * 2); - int to = offsets.at(i * 2 + 1); - Handle<String> substring = - isolate->factory()->NewProperSubString(subject, from, to); - elements->set(i, *substring); - }); - Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements); - result->set_length(Smi::FromInt(matches)); - return *result; -} - - RUNTIME_FUNCTION(Runtime_StringCharCodeAtRT) { HandleScope handle_scope(isolate); DCHECK(args.length() == 2); @@ -256,7 +194,7 @@ RUNTIME_FUNCTION(Runtime_StringCompare) { break; } UNREACHABLE(); - return Smi::FromInt(0); + return Smi::kZero; } @@ -573,13 +511,13 @@ static int CopyCachedOneByteCharsToArray(Heap* heap, const uint8_t* chars, elements->set(i, value, mode); } if (i < length) { - DCHECK(Smi::FromInt(0) == 0); + DCHECK(Smi::kZero == 0); memset(elements->data_start() + i, 0, kPointerSize * (length - i)); } #ifdef DEBUG for (int j = 0; j < length; ++j) { Object* element = elements->get(j); - DCHECK(element == Smi::FromInt(0) || + DCHECK(element == Smi::kZero || (element->IsString() && String::cast(element)->LooksValid())); } #endif @@ -942,7 +880,7 @@ RUNTIME_FUNCTION(Runtime_StringLessThan) { break; } UNREACHABLE(); - return Smi::FromInt(0); + return Smi::kZero; } RUNTIME_FUNCTION(Runtime_StringLessThanOrEqual) { @@ -960,7 +898,7 @@ RUNTIME_FUNCTION(Runtime_StringLessThanOrEqual) { break; } UNREACHABLE(); - return Smi::FromInt(0); + return Smi::kZero; } RUNTIME_FUNCTION(Runtime_StringGreaterThan) { @@ -978,7 +916,7 @@ RUNTIME_FUNCTION(Runtime_StringGreaterThan) { break; } UNREACHABLE(); - return Smi::FromInt(0); + return Smi::kZero; } RUNTIME_FUNCTION(Runtime_StringGreaterThanOrEqual) { @@ -996,7 +934,7 @@ RUNTIME_FUNCTION(Runtime_StringGreaterThanOrEqual) { break; } UNREACHABLE(); - return Smi::FromInt(0); + return Smi::kZero; } RUNTIME_FUNCTION(Runtime_StringEqual) { diff --git a/deps/v8/src/runtime/runtime-test.cc b/deps/v8/src/runtime/runtime-test.cc index 8100d2c759..7054192a0f 100644 --- a/deps/v8/src/runtime/runtime-test.cc +++ b/deps/v8/src/runtime/runtime-test.cc @@ -17,6 +17,7 @@ #include "src/snapshot/code-serializer.h" #include "src/snapshot/natives.h" #include "src/wasm/wasm-module.h" +#include "src/wasm/wasm-objects.h" namespace v8 { namespace internal { @@ -267,6 +268,9 @@ RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) { if (function->IsOptimized() && function->code()->is_turbofanned()) { return Smi::FromInt(7); // 7 == "TurboFan compiler". } + if (function->IsInterpreted()) { + return Smi::FromInt(8); // 8 == "Interpreted". + } return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes". : Smi::FromInt(2); // 2 == "no". } @@ -444,7 +448,7 @@ RUNTIME_FUNCTION(Runtime_DebugPrint) { OFStream os(stdout); #ifdef DEBUG - if (args[0]->IsString()) { + if (args[0]->IsString() && isolate->context() != nullptr) { // If we have a string, assume it's a code "marker" // and print some interesting cpu debugging info. JavaScriptFrameIterator it(isolate); @@ -546,8 +550,7 @@ RUNTIME_FUNCTION(Runtime_NativeScriptsCount) { return Smi::FromInt(Natives::GetBuiltinsCount()); } - -// Returns V8 version as a string. +// TODO(5510): remove this. RUNTIME_FUNCTION(Runtime_GetV8Version) { HandleScope scope(isolate); DCHECK(args.length() == 0); @@ -755,21 +758,37 @@ RUNTIME_FUNCTION(Runtime_SerializeWasmModule) { // Return undefined if unsuccessful. RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) { HandleScope shs(isolate); - DCHECK(args.length() == 1); + DCHECK(args.length() == 2); CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0); + CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, wire_bytes, 1); Address mem_start = static_cast<Address>(buffer->backing_store()); int mem_size = static_cast<int>(buffer->byte_length()->Number()); + // DeserializeWasmModule will allocate. We assume JSArrayBuffer doesn't + // get relocated. ScriptData sc(mem_start, mem_size); + bool already_external = wire_bytes->is_external(); + if (!already_external) { + wire_bytes->set_is_external(true); + isolate->heap()->UnregisterArrayBuffer(*wire_bytes); + } MaybeHandle<FixedArray> maybe_compiled_module = - WasmCompiledModuleSerializer::DeserializeWasmModule(isolate, &sc); + WasmCompiledModuleSerializer::DeserializeWasmModule( + isolate, &sc, + Vector<const uint8_t>( + reinterpret_cast<uint8_t*>(wire_bytes->backing_store()), + static_cast<int>(wire_bytes->byte_length()->Number()))); + if (!already_external) { + wire_bytes->set_is_external(false); + isolate->heap()->RegisterNewArrayBuffer(*wire_bytes); + } Handle<FixedArray> compiled_module; if (!maybe_compiled_module.ToHandle(&compiled_module)) { return isolate->heap()->undefined_value(); } - return *wasm::CreateCompiledModuleObject(isolate, compiled_module, - wasm::ModuleOrigin::kWasmOrigin); + return *WasmModuleObject::New( + isolate, Handle<WasmCompiledModule>::cast(compiled_module)); } RUNTIME_FUNCTION(Runtime_ValidateWasmInstancesChain) { diff --git a/deps/v8/src/runtime/runtime-typedarray.cc b/deps/v8/src/runtime/runtime-typedarray.cc index ba422bf01e..cb0e062d14 100644 --- a/deps/v8/src/runtime/runtime-typedarray.cc +++ b/deps/v8/src/runtime/runtime-typedarray.cc @@ -59,7 +59,7 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) { DCHECK(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0); if (array_buffer->backing_store() == NULL) { - CHECK(Smi::FromInt(0) == array_buffer->byte_length()); + CHECK(Smi::kZero == array_buffer->byte_length()); return isolate->heap()->undefined_value(); } // Shared array buffers should never be neutered. @@ -142,7 +142,7 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) { DCHECK_EQ(v8::ArrayBufferView::kInternalFieldCount, holder->GetInternalFieldCount()); for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { - holder->SetInternalField(i, Smi::FromInt(0)); + holder->SetInternalField(i, Smi::kZero); } Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); holder->set_length(*length_obj); @@ -215,7 +215,7 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) { DCHECK_EQ(v8::ArrayBufferView::kInternalFieldCount, holder->GetInternalFieldCount()); for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { - holder->SetInternalField(i, Smi::FromInt(0)); + holder->SetInternalField(i, Smi::kZero); } // NOTE: not initializing backing store. @@ -241,7 +241,7 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) { } holder->set_buffer(*buffer); - holder->set_byte_offset(Smi::FromInt(0)); + holder->set_byte_offset(Smi::kZero); Handle<Object> byte_length_obj( isolate->factory()->NewNumberFromSize(byte_length)); holder->set_byte_length(*byte_length_obj); diff --git a/deps/v8/src/runtime/runtime.h b/deps/v8/src/runtime/runtime.h index cbdaf0f033..8e2e83c37e 100644 --- a/deps/v8/src/runtime/runtime.h +++ b/deps/v8/src/runtime/runtime.h @@ -9,6 +9,7 @@ #include "src/allocation.h" #include "src/base/platform/time.h" +#include "src/globals.h" #include "src/objects.h" #include "src/unicode.h" #include "src/zone/zone.h" @@ -51,13 +52,12 @@ namespace internal { F(HasComplexElements, 1, 1) \ F(IsArray, 1, 1) \ F(ArrayIsArray, 1, 1) \ - F(HasCachedArrayIndex, 1, 1) \ - F(GetCachedArrayIndex, 1, 1) \ F(FixedArrayGet, 2, 1) \ F(FixedArraySet, 3, 1) \ F(ArraySpeciesConstructor, 1, 1) \ F(ArrayIncludes_Slow, 3, 1) \ - F(ArrayIndexOf, 3, 1) + F(ArrayIndexOf, 3, 1) \ + F(SpreadIterablePrepare, 1, 1) #define FOR_EACH_INTRINSIC_ATOMICS(F) \ F(ThrowNotIntegerSharedTypedArrayError, 1, 1) \ @@ -188,6 +188,7 @@ namespace internal { F(ScriptLineStartPosition, 2, 1) \ F(ScriptLineEndPosition, 2, 1) \ F(ScriptLocationFromLine, 4, 1) \ + F(ScriptLocationFromLine2, 4, 1) \ F(ScriptPositionInfo, 3, 1) \ F(ScriptSourceLine, 2, 1) \ F(DebugPrepareStepInIfStepping, 1, 1) \ @@ -195,11 +196,10 @@ namespace internal { F(DebugRecordAsyncFunction, 1, 1) \ F(DebugPushPromise, 1, 1) \ F(DebugPopPromise, 0, 1) \ - F(DebugAsyncTaskEvent, 1, 1) \ + F(DebugNextMicrotaskId, 0, 1) \ + F(DebugAsyncTaskEvent, 3, 1) \ F(DebugIsActive, 0, 1) \ - F(DebugBreakInOptimizedCode, 0, 1) \ - F(GetWasmFunctionOffsetTable, 1, 1) \ - F(DisassembleWasmFunction, 1, 1) + F(DebugBreakInOptimizedCode, 0, 1) #define FOR_EACH_INTRINSIC_ERROR(F) F(ErrorToString, 1, 1) @@ -214,13 +214,15 @@ namespace internal { F(InterpreterTraceBytecodeEntry, 3, 1) \ F(InterpreterTraceBytecodeExit, 3, 1) \ F(InterpreterClearPendingMessage, 0, 1) \ - F(InterpreterSetPendingMessage, 1, 1) + F(InterpreterSetPendingMessage, 1, 1) \ + F(InterpreterAdvanceBytecodeOffset, 2, 1) #define FOR_EACH_INTRINSIC_FUNCTION(F) \ F(FunctionGetName, 1, 1) \ F(FunctionSetName, 2, 1) \ F(FunctionRemovePrototype, 1, 1) \ F(FunctionGetScript, 1, 1) \ + F(FunctionGetScriptId, 1, 1) \ F(FunctionGetSourceCode, 1, 1) \ F(FunctionGetScriptSourcePosition, 1, 1) \ F(FunctionGetContextData, 1, 1) \ @@ -290,7 +292,8 @@ namespace internal { F(CheckIsBootstrapping, 0, 1) \ F(CreateListFromArrayLike, 1, 1) \ F(EnqueueMicrotask, 1, 1) \ - F(EnqueuePromiseResolveThenableJob, 6, 1) \ + F(EnqueuePromiseReactionJob, 4, 1) \ + F(EnqueuePromiseResolveThenableJob, 3, 1) \ F(GetAndResetRuntimeCallStats, -1 /* <= 2 */, 1) \ F(ExportExperimentalFromRuntime, 1, 1) \ F(ExportFromRuntime, 1, 1) \ @@ -298,12 +301,13 @@ namespace internal { F(InstallToContext, 1, 1) \ F(Interrupt, 0, 1) \ F(IS_VAR, 1, 1) \ - F(IsWasmObject, 1, 1) \ + F(IsWasmInstance, 1, 1) \ F(NewReferenceError, 2, 1) \ F(NewSyntaxError, 2, 1) \ F(NewTypeError, 2, 1) \ F(OrdinaryHasInstance, 2, 1) \ - F(PromiseRejectEvent, 3, 1) \ + F(PromiseReject, 3, 1) \ + F(PromiseFulfill, 4, 1) \ F(PromiseRejectEventFromStack, 2, 1) \ F(PromiseRevokeReject, 1, 1) \ F(PromoteScheduledException, 0, 1) \ @@ -325,6 +329,7 @@ namespace internal { F(ThrowNotGeneric, 1, 1) \ F(ThrowReferenceError, 1, 1) \ F(ThrowStackOverflow, 0, 1) \ + F(ThrowTypeError, -1 /* >= 1 */, 1) \ F(ThrowWasmError, 2, 1) \ F(ThrowUndefinedOrNullToObject, 1, 1) \ F(Typeof, 1, 1) \ @@ -350,7 +355,12 @@ namespace internal { F(LiveEditCompareStrings, 2, 1) \ F(LiveEditRestartFrame, 2, 1) -#define FOR_EACH_INTRINSIC_MATHS(F) F(GenerateRandomNumbers, 1, 1) +#define FOR_EACH_INTRINSIC_MATHS(F) F(GenerateRandomNumbers, 0, 1) + +#define FOR_EACH_INTRINSIC_MODULE(F) \ + F(GetModuleNamespace, 1, 1) \ + F(LoadModuleVariable, 1, 1) \ + F(StoreModuleVariable, 2, 1) #define FOR_EACH_INTRINSIC_NUMBERS(F) \ F(IsValidSmi, 1, 1) \ @@ -370,13 +380,11 @@ namespace internal { #define FOR_EACH_INTRINSIC_OBJECT(F) \ F(GetPrototype, 1, 1) \ F(ObjectHasOwnProperty, 2, 1) \ + F(ObjectCreate, 2, 1) \ F(InternalSetPrototype, 2, 1) \ - F(SetPrototype, 2, 1) \ F(OptimizeObjectForAddingMultipleProperties, 2, 1) \ F(GetProperty, 2, 1) \ F(KeyedGetProperty, 2, 1) \ - F(StoreGlobalViaContext_Sloppy, 2, 1) \ - F(StoreGlobalViaContext_Strict, 2, 1) \ F(AddNamedProperty, 4, 1) \ F(SetProperty, 4, 1) \ F(AddElement, 3, 1) \ @@ -417,11 +425,9 @@ namespace internal { F(Compare, 3, 1) \ F(HasInPrototypeChain, 2, 1) \ F(CreateIterResultObject, 2, 1) \ + F(CreateKeyValueArray, 2, 1) \ F(IsAccessCheckNeeded, 1, 1) \ - F(CreateDataProperty, 3, 1) \ - F(LoadModuleExport, 1, 1) \ - F(LoadModuleImport, 2, 1) \ - F(StoreModuleExport, 2, 1) + F(CreateDataProperty, 3, 1) #define FOR_EACH_INTRINSIC_OPERATORS(F) \ F(Multiply, 2, 1) \ @@ -453,17 +459,17 @@ namespace internal { F(JSProxyGetHandler, 1, 1) \ F(JSProxyRevoke, 1, 1) -#define FOR_EACH_INTRINSIC_REGEXP(F) \ - F(StringReplaceGlobalRegExpWithString, 4, 1) \ - F(StringSplit, 3, 1) \ - F(RegExpExec, 4, 1) \ - F(RegExpFlags, 1, 1) \ - F(RegExpSource, 1, 1) \ - F(RegExpConstructResult, 3, 1) \ - F(RegExpInitializeAndCompile, 3, 1) \ - F(RegExpExecMultiple, 4, 1) \ - F(RegExpExecReThrow, 4, 1) \ - F(IsRegExp, 1, 1) +#define FOR_EACH_INTRINSIC_REGEXP(F) \ + F(IsRegExp, 1, 1) \ + F(RegExpCreate, 1, 1) \ + F(RegExpExec, 4, 1) \ + F(RegExpExecMultiple, 4, 1) \ + F(RegExpExecReThrow, 4, 1) \ + F(RegExpInternalReplace, 3, 1) \ + F(RegExpReplace, 3, 1) \ + F(StringReplaceGlobalRegExpWithString, 4, 1) \ + F(StringReplaceNonGlobalRegExpWithFunction, 3, 1) \ + F(StringSplit, 3, 1) #define FOR_EACH_INTRINSIC_SCOPES(F) \ F(ThrowConstAssignError, 0, 1) \ @@ -807,7 +813,6 @@ namespace internal { F(SubString, 3, 1) \ F(StringAdd, 2, 1) \ F(InternalizeString, 1, 1) \ - F(StringMatch, 3, 1) \ F(StringCharCodeAtRT, 2, 1) \ F(StringCompare, 2, 1) \ F(StringBuilderConcat, 3, 1) \ @@ -891,7 +896,7 @@ namespace internal { F(HasFixedUint8ClampedElements, 1, 1) \ F(SpeciesProtector, 0, 1) \ F(SerializeWasmModule, 1, 1) \ - F(DeserializeWasmModule, 1, 1) \ + F(DeserializeWasmModule, 2, 1) \ F(IsAsmWasmCode, 1, 1) \ F(IsNotAsmWasmCode, 1, 1) \ F(ValidateWasmInstancesChain, 2, 1) \ @@ -971,6 +976,7 @@ namespace internal { FOR_EACH_INTRINSIC_LITERALS(F) \ FOR_EACH_INTRINSIC_LIVEEDIT(F) \ FOR_EACH_INTRINSIC_MATHS(F) \ + FOR_EACH_INTRINSIC_MODULE(F) \ FOR_EACH_INTRINSIC_NUMBERS(F) \ FOR_EACH_INTRINSIC_OBJECT(F) \ FOR_EACH_INTRINSIC_OPERATORS(F) \ @@ -1039,7 +1045,7 @@ class Runtime : public AllStatic { static const Function* FunctionForName(const unsigned char* name, int length); // Get the intrinsic function with the given FunctionId. - static const Function* FunctionForId(FunctionId id); + V8_EXPORT_PRIVATE static const Function* FunctionForId(FunctionId id); // Get the intrinsic function with the given function entry address. static const Function* FunctionForEntry(Address ref); @@ -1114,8 +1120,7 @@ class RuntimeState { DISALLOW_COPY_AND_ASSIGN(RuntimeState); }; - -std::ostream& operator<<(std::ostream&, Runtime::FunctionId); +V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, Runtime::FunctionId); //--------------------------------------------------------------------------- // Constants used by interface to runtime functions. |