| Index: src/runtime/runtime-test.cc
|
| diff --git a/src/runtime/runtime-test.cc b/src/runtime/runtime-test.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..eac3c613af910ca7fa4e61909324d21d06612031
|
| --- /dev/null
|
| +++ b/src/runtime/runtime-test.cc
|
| @@ -0,0 +1,323 @@
|
| +// Copyright 2014 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/v8.h"
|
| +
|
| +#include "src/arguments.h"
|
| +#include "src/deoptimizer.h"
|
| +#include "src/full-codegen.h"
|
| +#include "src/runtime/runtime.h"
|
| +#include "src/runtime/runtime-utils.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +
|
| +RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
| + if (!function->IsOptimized()) return isolate->heap()->undefined_value();
|
| +
|
| + // TODO(turbofan): Deoptimization is not supported yet.
|
| + if (function->code()->is_turbofanned() && !FLAG_turbo_deoptimization) {
|
| + return isolate->heap()->undefined_value();
|
| + }
|
| +
|
| + Deoptimizer::DeoptimizeFunction(*function);
|
| +
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 0);
|
| +#if defined(USE_SIMULATOR)
|
| + return isolate->heap()->true_value();
|
| +#else
|
| + return isolate->heap()->false_value();
|
| +#endif
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 0);
|
| + return isolate->heap()->ToBoolean(
|
| + isolate->concurrent_recompilation_enabled());
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
|
| + HandleScope scope(isolate);
|
| + RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
| + // The following two assertions are lifted from the DCHECKs inside
|
| + // JSFunction::MarkForOptimization().
|
| + RUNTIME_ASSERT(!function->shared()->is_generator());
|
| + RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
|
| + (function->code()->kind() == Code::FUNCTION &&
|
| + function->code()->optimizable()));
|
| +
|
| + // If the function is optimized, just return.
|
| + if (function->IsOptimized()) return isolate->heap()->undefined_value();
|
| +
|
| + function->MarkForOptimization();
|
| +
|
| + Code* unoptimized = function->shared()->code();
|
| + if (args.length() == 2 && unoptimized->kind() == Code::FUNCTION) {
|
| + CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
|
| + if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("osr")) && FLAG_use_osr) {
|
| + // Start patching from the currently patched loop nesting level.
|
| + DCHECK(BackEdgeTable::Verify(isolate, unoptimized));
|
| + isolate->runtime_profiler()->AttemptOnStackReplacement(
|
| + *function, Code::kMaxLoopNestingMarker);
|
| + } else if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
|
| + isolate->concurrent_recompilation_enabled()) {
|
| + function->MarkForConcurrentOptimization();
|
| + }
|
| + }
|
| +
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_CHECKED(JSFunction, function, 0);
|
| + function->shared()->set_optimization_disabled(true);
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
|
| + HandleScope scope(isolate);
|
| + RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
|
| + if (!isolate->use_crankshaft()) {
|
| + return Smi::FromInt(4); // 4 == "never".
|
| + }
|
| + bool sync_with_compiler_thread = true;
|
| + if (args.length() == 2) {
|
| + CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
|
| + if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
|
| + sync_with_compiler_thread = false;
|
| + }
|
| + }
|
| + CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
| + if (isolate->concurrent_recompilation_enabled() &&
|
| + sync_with_compiler_thread) {
|
| + while (function->IsInOptimizationQueue()) {
|
| + isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
|
| + base::OS::Sleep(50);
|
| + }
|
| + }
|
| + if (FLAG_always_opt) {
|
| + // We may have always opt, but that is more best-effort than a real
|
| + // promise, so we still say "no" if it is not optimized.
|
| + return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always".
|
| + : Smi::FromInt(2); // 2 == "no".
|
| + }
|
| + if (FLAG_deopt_every_n_times) {
|
| + return Smi::FromInt(6); // 6 == "maybe deopted".
|
| + }
|
| + if (function->IsOptimized() && function->code()->is_turbofanned()) {
|
| + return Smi::FromInt(7); // 7 == "TurboFan compiler".
|
| + }
|
| + return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
|
| + : Smi::FromInt(2); // 2 == "no".
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
|
| + DCHECK(args.length() == 0);
|
| + RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
|
| + RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
|
| + isolate->optimizing_compiler_thread()->Unblock();
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
| + return Smi::FromInt(function->shared()->opt_count());
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
| + function->shared()->ClearTypeFeedbackInfo();
|
| + Code* unoptimized = function->shared()->code();
|
| + if (unoptimized->kind() == Code::FUNCTION) {
|
| + unoptimized->ClearInlineCaches();
|
| + }
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 0);
|
| + isolate->heap()->NotifyContextDisposed();
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 2 || args.length() == 3);
|
| +#ifdef DEBUG
|
| + CONVERT_SMI_ARG_CHECKED(interval, 0);
|
| + CONVERT_SMI_ARG_CHECKED(timeout, 1);
|
| + isolate->heap()->set_allocation_timeout(timeout);
|
| + FLAG_gc_interval = interval;
|
| + if (args.length() == 3) {
|
| + // Enable/disable inline allocation if requested.
|
| + CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
|
| + if (inline_allocation) {
|
| + isolate->heap()->EnableInlineAllocation();
|
| + } else {
|
| + isolate->heap()->DisableInlineAllocation();
|
| + }
|
| + }
|
| +#endif
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_DebugPrint) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 1);
|
| +
|
| + OFStream os(stdout);
|
| +#ifdef DEBUG
|
| + if (args[0]->IsString()) {
|
| + // If we have a string, assume it's a code "marker"
|
| + // and print some interesting cpu debugging info.
|
| + JavaScriptFrameIterator it(isolate);
|
| + JavaScriptFrame* frame = it.frame();
|
| + os << "fp = " << frame->fp() << ", sp = " << frame->sp()
|
| + << ", caller_sp = " << frame->caller_sp() << ": ";
|
| + } else {
|
| + os << "DebugPrint: ";
|
| + }
|
| + args[0]->Print(os);
|
| + if (args[0]->IsHeapObject()) {
|
| + os << "\n";
|
| + HeapObject::cast(args[0])->map()->Print(os);
|
| + }
|
| +#else
|
| + // ShortPrint is available in release mode. Print is not.
|
| + os << Brief(args[0]);
|
| +#endif
|
| + os << endl;
|
| +
|
| + return args[0]; // return TOS
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_DebugTrace) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 0);
|
| + isolate->PrintStack(stdout);
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +// This will not allocate (flatten the string), but it may run
|
| +// very slowly for very deeply nested ConsStrings. For debugging use only.
|
| +RUNTIME_FUNCTION(Runtime_GlobalPrint) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 1);
|
| +
|
| + CONVERT_ARG_CHECKED(String, string, 0);
|
| + ConsStringIteratorOp op;
|
| + StringCharacterStream stream(string, &op);
|
| + while (stream.HasMore()) {
|
| + uint16_t character = stream.GetNext();
|
| + PrintF("%c", character);
|
| + }
|
| + return string;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_SystemBreak) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 0);
|
| + base::OS::DebugBreak();
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +// Sets a v8 flag.
|
| +RUNTIME_FUNCTION(Runtime_SetFlags) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_CHECKED(String, arg, 0);
|
| + SmartArrayPointer<char> flags =
|
| + arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
|
| + FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_Abort) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_SMI_ARG_CHECKED(message_id, 0);
|
| + const char* message =
|
| + GetBailoutReason(static_cast<BailoutReason>(message_id));
|
| + base::OS::PrintError("abort: %s\n", message);
|
| + isolate->PrintStack(stderr);
|
| + base::OS::Abort();
|
| + UNREACHABLE();
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_AbortJS) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
|
| + base::OS::PrintError("abort: %s\n", message->ToCString().get());
|
| + isolate->PrintStack(stderr);
|
| + base::OS::Abort();
|
| + UNREACHABLE();
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_HaveSameMap) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 2);
|
| + CONVERT_ARG_CHECKED(JSObject, obj1, 0);
|
| + CONVERT_ARG_CHECKED(JSObject, obj2, 1);
|
| + return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
|
| +}
|
| +
|
| +
|
| +#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
|
| + RUNTIME_FUNCTION(Runtime_Has##Name) { \
|
| + CONVERT_ARG_CHECKED(JSObject, obj, 0); \
|
| + return isolate->heap()->ToBoolean(obj->Has##Name()); \
|
| + }
|
| +
|
| +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
|
| +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
|
| +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
|
| +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
|
| +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
|
| +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
|
| +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
|
| +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
|
| +// Properties test sitting with elements tests - not fooling anyone.
|
| +ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
|
| +
|
| +#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
|
| +}
|
| +} // namespace v8::internal
|
|
|