diff options
Diffstat (limited to 'deps/v8/src/runtime/runtime-test.cc')
-rw-r--r-- | deps/v8/src/runtime/runtime-test.cc | 218 |
1 files changed, 160 insertions, 58 deletions
diff --git a/deps/v8/src/runtime/runtime-test.cc b/deps/v8/src/runtime/runtime-test.cc index 7054192a0f..bea7245c35 100644 --- a/deps/v8/src/runtime/runtime-test.cc +++ b/deps/v8/src/runtime/runtime-test.cc @@ -19,12 +19,51 @@ #include "src/wasm/wasm-module.h" #include "src/wasm/wasm-objects.h" +namespace { +struct WasmCompileControls { + uint32_t MaxWasmBufferSize = std::numeric_limits<uint32_t>::max(); + bool AllowAnySizeForAsync = true; +}; + +// We need per-isolate controls, because we sometimes run tests in multiple +// isolates +// concurrently. +// To avoid upsetting the static initializer count, we lazy initialize this. +v8::base::LazyInstance<std::map<v8::Isolate*, WasmCompileControls>>::type + g_PerIsolateWasmControls = LAZY_INSTANCE_INITIALIZER; + +bool IsWasmCompileAllowed(v8::Isolate* isolate, v8::Local<v8::Value> value, + bool is_async) { + DCHECK_GT(g_PerIsolateWasmControls.Get().count(isolate), 0); + const WasmCompileControls& ctrls = g_PerIsolateWasmControls.Get().at(isolate); + return (is_async && ctrls.AllowAnySizeForAsync) || + (v8::Local<v8::ArrayBuffer>::Cast(value)->ByteLength() <= + ctrls.MaxWasmBufferSize); +} + +// Use the compile controls for instantiation, too +bool IsWasmInstantiateAllowed(v8::Isolate* isolate, + v8::Local<v8::Value> module_or_bytes, + v8::MaybeLocal<v8::Value> ffi, bool is_async) { + DCHECK_GT(g_PerIsolateWasmControls.Get().count(isolate), 0); + const WasmCompileControls& ctrls = g_PerIsolateWasmControls.Get().at(isolate); + if (is_async && ctrls.AllowAnySizeForAsync) return true; + if (!module_or_bytes->IsWebAssemblyCompiledModule()) { + return IsWasmCompileAllowed(isolate, module_or_bytes, is_async); + } + v8::Local<v8::WasmCompiledModule> module = + v8::Local<v8::WasmCompiledModule>::Cast(module_or_bytes); + return static_cast<uint32_t>(module->GetWasmWireBytes()->Length()) <= + ctrls.MaxWasmBufferSize; +} +} // namespace + namespace v8 { namespace internal { RUNTIME_FUNCTION(Runtime_ConstructDouble) { HandleScope scope(isolate); - DCHECK(args.length() == 2); + DCHECK_EQ(2, args.length()); CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]); CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]); uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo; @@ -33,7 +72,7 @@ RUNTIME_FUNCTION(Runtime_ConstructDouble) { RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) { HandleScope scope(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); // This function is used by fuzzers to get coverage in compiler. // Ignore calls on non-function objects to avoid runtime errors. @@ -48,7 +87,7 @@ RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) { // TODO(turbofan): Deoptimization is not supported yet. if (function->code()->is_turbofanned() && - function->shared()->asm_function() && !FLAG_turbo_asm_deoptimization) { + function->shared()->asm_function()) { return isolate->heap()->undefined_value(); } @@ -60,7 +99,7 @@ RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) { RUNTIME_FUNCTION(Runtime_DeoptimizeNow) { HandleScope scope(isolate); - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); Handle<JSFunction> function; @@ -74,7 +113,7 @@ RUNTIME_FUNCTION(Runtime_DeoptimizeNow) { // TODO(turbofan): Deoptimization is not supported yet. if (function->code()->is_turbofanned() && - function->shared()->asm_function() && !FLAG_turbo_asm_deoptimization) { + function->shared()->asm_function()) { return isolate->heap()->undefined_value(); } @@ -86,7 +125,7 @@ RUNTIME_FUNCTION(Runtime_DeoptimizeNow) { RUNTIME_FUNCTION(Runtime_RunningInSimulator) { SealHandleScope shs(isolate); - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); #if defined(USE_SIMULATOR) return isolate->heap()->true_value(); #else @@ -97,7 +136,7 @@ RUNTIME_FUNCTION(Runtime_RunningInSimulator) { RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) { SealHandleScope shs(isolate); - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); return isolate->heap()->ToBoolean( isolate->concurrent_recompilation_enabled()); } @@ -127,6 +166,12 @@ RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) { return isolate->heap()->undefined_value(); } + // If function isn't compiled, compile it now. + if (!function->shared()->is_compiled() && + !Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)) { + return isolate->heap()->undefined_value(); + } + // If the function is already optimized, just return. if (function->IsOptimized()) return isolate->heap()->undefined_value(); @@ -146,7 +191,7 @@ RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) { RUNTIME_FUNCTION(Runtime_InterpretFunctionOnNextCall) { HandleScope scope(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0); if (!function_object->IsJSFunction()) { return isolate->heap()->undefined_value(); @@ -164,13 +209,19 @@ RUNTIME_FUNCTION(Runtime_InterpretFunctionOnNextCall) { RUNTIME_FUNCTION(Runtime_BaselineFunctionOnNextCall) { HandleScope scope(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0); if (!function_object->IsJSFunction()) { return isolate->heap()->undefined_value(); } Handle<JSFunction> function = Handle<JSFunction>::cast(function_object); + // If function isn't compiled, compile it now. + if (!function->shared()->is_compiled() && + !Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)) { + return isolate->heap()->undefined_value(); + } + // Do not tier down if we are already on optimized code. Replacing optimized // code without actual deoptimization can lead to funny bugs. if (function->code()->kind() != Code::OPTIMIZED_FUNCTION && @@ -216,7 +267,7 @@ RUNTIME_FUNCTION(Runtime_OptimizeOsr) { RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) { HandleScope scope(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_CHECKED(JSFunction, function, 0); function->shared()->set_disable_optimization_reason( kOptimizationDisabledForTest); @@ -277,7 +328,7 @@ RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) { RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) { - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); if (FLAG_block_concurrent_recompilation && isolate->concurrent_recompilation_enabled()) { isolate->optimizing_compile_dispatcher()->Unblock(); @@ -288,19 +339,23 @@ RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) { RUNTIME_FUNCTION(Runtime_GetOptimizationCount) { HandleScope scope(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); return Smi::FromInt(function->shared()->opt_count()); } +static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) { + args.GetReturnValue().Set(args.This()); +} RUNTIME_FUNCTION(Runtime_GetUndetectable) { HandleScope scope(isolate); - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); Local<v8::ObjectTemplate> desc = v8::ObjectTemplate::New(v8_isolate); desc->MarkAsUndetectable(); + desc->SetCallAsFunctionHandler(ReturnThis); Local<v8::Object> obj; if (!desc->NewInstance(v8_isolate->GetCurrentContext()).ToLocal(&obj)) { return nullptr; @@ -323,7 +378,7 @@ static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) { // parameters when it is called. RUNTIME_FUNCTION(Runtime_GetCallable) { HandleScope scope(isolate); - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(v8_isolate); Local<ObjectTemplate> instance_template = t->InstanceTemplate(); @@ -339,7 +394,7 @@ RUNTIME_FUNCTION(Runtime_GetCallable) { RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) { HandleScope scope(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); function->ClearTypeFeedbackInfo(); Code* unoptimized = function->shared()->code(); @@ -412,9 +467,29 @@ RUNTIME_FUNCTION(Runtime_CheckWasmWrapperElision) { return isolate->heap()->ToBoolean(count == 1); } +RUNTIME_FUNCTION(Runtime_SetWasmCompileControls) { + HandleScope scope(isolate); + v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); + CHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(Smi, block_size, 0); + CONVERT_BOOLEAN_ARG_CHECKED(allow_async, 1); + WasmCompileControls& ctrl = (*g_PerIsolateWasmControls.Pointer())[v8_isolate]; + ctrl.AllowAnySizeForAsync = allow_async; + ctrl.MaxWasmBufferSize = static_cast<uint32_t>(block_size->value()); + isolate->set_allow_wasm_compile_callback(IsWasmCompileAllowed); + return isolate->heap()->undefined_value(); +} + +RUNTIME_FUNCTION(Runtime_SetWasmInstantiateControls) { + HandleScope scope(isolate); + CHECK(args.length() == 0); + isolate->set_allow_wasm_instantiate_callback(IsWasmInstantiateAllowed); + return isolate->heap()->undefined_value(); +} + RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) { HandleScope scope(isolate); - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); isolate->heap()->NotifyContextDisposed(true); return isolate->heap()->undefined_value(); } @@ -444,7 +519,7 @@ RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) { RUNTIME_FUNCTION(Runtime_DebugPrint) { SealHandleScope shs(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); OFStream os(stdout); #ifdef DEBUG @@ -475,7 +550,7 @@ RUNTIME_FUNCTION(Runtime_DebugPrint) { RUNTIME_FUNCTION(Runtime_DebugTrace) { SealHandleScope shs(isolate); - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); isolate->PrintStack(stdout); return isolate->heap()->undefined_value(); } @@ -485,7 +560,7 @@ RUNTIME_FUNCTION(Runtime_DebugTrace) { // very slowly for very deeply nested ConsStrings. For debugging use only. RUNTIME_FUNCTION(Runtime_GlobalPrint) { SealHandleScope shs(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_CHECKED(String, string, 0); StringCharacterStream stream(string); @@ -501,7 +576,7 @@ RUNTIME_FUNCTION(Runtime_SystemBreak) { // The code below doesn't create handles, but when breaking here in GDB // having a handle scope might be useful. HandleScope scope(isolate); - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); base::OS::DebugBreak(); return isolate->heap()->undefined_value(); } @@ -510,7 +585,7 @@ RUNTIME_FUNCTION(Runtime_SystemBreak) { // Sets a v8 flag. RUNTIME_FUNCTION(Runtime_SetFlags) { SealHandleScope shs(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_CHECKED(String, arg, 0); std::unique_ptr<char[]> flags = arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); @@ -521,7 +596,7 @@ RUNTIME_FUNCTION(Runtime_SetFlags) { RUNTIME_FUNCTION(Runtime_Abort) { SealHandleScope shs(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_SMI_ARG_CHECKED(message_id, 0); const char* message = GetBailoutReason(static_cast<BailoutReason>(message_id)); @@ -535,7 +610,7 @@ RUNTIME_FUNCTION(Runtime_Abort) { RUNTIME_FUNCTION(Runtime_AbortJS) { HandleScope scope(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_HANDLE_CHECKED(String, message, 0); base::OS::PrintError("abort: %s\n", message->ToCString().get()); isolate->PrintStack(stderr); @@ -546,14 +621,14 @@ RUNTIME_FUNCTION(Runtime_AbortJS) { RUNTIME_FUNCTION(Runtime_NativeScriptsCount) { - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); return Smi::FromInt(Natives::GetBuiltinsCount()); } // TODO(5510): remove this. RUNTIME_FUNCTION(Runtime_GetV8Version) { HandleScope scope(isolate); - DCHECK(args.length() == 0); + DCHECK_EQ(0, args.length()); const char* version_string = v8::V8::GetVersion(); @@ -564,7 +639,7 @@ RUNTIME_FUNCTION(Runtime_GetV8Version) { RUNTIME_FUNCTION(Runtime_DisassembleFunction) { HandleScope scope(isolate); #ifdef DEBUG - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); // Get the function and make sure it is compiled. CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0); if (!Compiler::Compile(func, Compiler::KEEP_EXCEPTION)) { @@ -628,7 +703,7 @@ RUNTIME_FUNCTION(Runtime_TraceTailCall) { RUNTIME_FUNCTION(Runtime_GetExceptionDetails) { HandleScope shs(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_HANDLE_CHECKED(JSObject, exception_obj, 0); Factory* factory = isolate->factory(); @@ -653,7 +728,7 @@ RUNTIME_FUNCTION(Runtime_GetExceptionDetails) { RUNTIME_FUNCTION(Runtime_HaveSameMap) { SealHandleScope shs(isolate); - DCHECK(args.length() == 2); + DCHECK_EQ(2, args.length()); CONVERT_ARG_CHECKED(JSObject, obj1, 0); CONVERT_ARG_CHECKED(JSObject, obj2, 1); return isolate->heap()->ToBoolean(obj1->map() == obj2->map()); @@ -662,41 +737,48 @@ RUNTIME_FUNCTION(Runtime_HaveSameMap) { RUNTIME_FUNCTION(Runtime_InNewSpace) { SealHandleScope shs(isolate); - DCHECK(args.length() == 1); + DCHECK_EQ(1, args.length()); CONVERT_ARG_CHECKED(Object, obj, 0); return isolate->heap()->ToBoolean(isolate->heap()->InNewSpace(obj)); } -static bool IsAsmWasmCode(Isolate* isolate, Handle<JSFunction> function) { +RUNTIME_FUNCTION(Runtime_IsAsmWasmCode) { + SealHandleScope shs(isolate); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_CHECKED(JSFunction, function, 0); if (!function->shared()->HasAsmWasmData()) { // Doesn't have wasm data. - return false; + return isolate->heap()->false_value(); } if (function->shared()->code() != isolate->builtins()->builtin(Builtins::kInstantiateAsmJs)) { // Hasn't been compiled yet. - return false; + return isolate->heap()->false_value(); } - return true; + return isolate->heap()->true_value(); } -RUNTIME_FUNCTION(Runtime_IsAsmWasmCode) { +namespace { +bool DisallowCodegenFromStringsCallback(v8::Local<v8::Context> context) { + return false; +} +} + +RUNTIME_FUNCTION(Runtime_DisallowCodegenFromStrings) { SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); - // TODO(mstarzinger): --always-opt should still allow asm.js->wasm, - // but currently does not. For now, pretend asm.js->wasm is on for - // this case. Be more accurate once this is corrected. - return isolate->heap()->ToBoolean( - ((FLAG_always_opt || FLAG_prepare_always_opt) && FLAG_validate_asm) || - IsAsmWasmCode(isolate, function)); + DCHECK_EQ(0, args.length()); + v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); + v8_isolate->SetAllowCodeGenerationFromStringsCallback( + DisallowCodegenFromStringsCallback); + return isolate->heap()->undefined_value(); } -RUNTIME_FUNCTION(Runtime_IsNotAsmWasmCode) { +RUNTIME_FUNCTION(Runtime_IsWasmCode) { SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); - return isolate->heap()->ToBoolean(!IsAsmWasmCode(isolate, function)); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_CHECKED(JSFunction, function, 0); + bool is_js_to_wasm = function->code()->kind() == Code::JS_TO_WASM_FUNCTION; + return isolate->heap()->ToBoolean(is_js_to_wasm); } #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \ @@ -736,15 +818,18 @@ RUNTIME_FUNCTION(Runtime_SpeciesProtector) { return isolate->heap()->ToBoolean(isolate->IsArraySpeciesLookupChainIntact()); } +#define CONVERT_ARG_HANDLE_CHECKED_2(Type, name, index) \ + CHECK(Type::Is##Type(args[index])); \ + Handle<Type> name = args.at<Type>(index); + // Take a compiled wasm module, serialize it and copy the buffer into an array // buffer, which is then returned. RUNTIME_FUNCTION(Runtime_SerializeWasmModule) { HandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, module_obj, 0); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_HANDLE_CHECKED_2(WasmModuleObject, module_obj, 0); - Handle<FixedArray> orig = - handle(FixedArray::cast(module_obj->GetInternalField(0))); + Handle<WasmCompiledModule> orig(module_obj->compiled_module()); std::unique_ptr<ScriptData> data = WasmCompiledModuleSerializer::SerializeWasmModule(isolate, orig); void* buff = isolate->array_buffer_allocator()->Allocate(data->length()); @@ -758,7 +843,7 @@ RUNTIME_FUNCTION(Runtime_SerializeWasmModule) { // Return undefined if unsuccessful. RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) { HandleScope shs(isolate); - DCHECK(args.length() == 2); + DCHECK_EQ(2, args.length()); CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0); CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, wire_bytes, 1); @@ -793,8 +878,8 @@ RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) { RUNTIME_FUNCTION(Runtime_ValidateWasmInstancesChain) { HandleScope shs(isolate); - DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(JSObject, module_obj, 0); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED_2(WasmModuleObject, module_obj, 0); CONVERT_ARG_HANDLE_CHECKED(Smi, instance_count, 1); wasm::testing::ValidateInstancesChain(isolate, module_obj, instance_count->value()); @@ -803,17 +888,34 @@ RUNTIME_FUNCTION(Runtime_ValidateWasmInstancesChain) { RUNTIME_FUNCTION(Runtime_ValidateWasmModuleState) { HandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, module_obj, 0); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_HANDLE_CHECKED_2(WasmModuleObject, module_obj, 0); wasm::testing::ValidateModuleState(isolate, module_obj); return isolate->heap()->ToBoolean(true); } RUNTIME_FUNCTION(Runtime_ValidateWasmOrphanedInstance) { HandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0); - wasm::testing::ValidateOrphanedInstance(isolate, instance_obj); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_HANDLE_CHECKED_2(WasmInstanceObject, instance, 0); + wasm::testing::ValidateOrphanedInstance(isolate, instance); + return isolate->heap()->ToBoolean(true); +} + +RUNTIME_FUNCTION(Runtime_Verify) { + HandleScope shs(isolate); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); +#ifdef VERIFY_HEAP + object->ObjectVerify(); +#else + CHECK(object->IsObject()); + if (object->IsHeapObject()) { + CHECK(HeapObject::cast(*object)->map()->IsMap()); + } else { + CHECK(object->IsSmi()); + } +#endif return isolate->heap()->ToBoolean(true); } |