1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "src/arguments.h"
8 #include "src/deoptimizer.h"
9 #include "src/full-codegen.h"
10 #include "src/natives.h"
11 #include "src/runtime/runtime-utils.h"
16 RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
17 HandleScope scope(isolate);
18 DCHECK(args.length() == 1);
19 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
20 if (!function->IsOptimized()) return isolate->heap()->undefined_value();
22 // TODO(turbofan): Deoptimization is not supported yet.
23 if (function->code()->is_turbofanned() && !FLAG_turbo_deoptimization) {
24 return isolate->heap()->undefined_value();
27 Deoptimizer::DeoptimizeFunction(*function);
29 return isolate->heap()->undefined_value();
33 RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
34 SealHandleScope shs(isolate);
35 DCHECK(args.length() == 0);
36 #if defined(USE_SIMULATOR)
37 return isolate->heap()->true_value();
39 return isolate->heap()->false_value();
44 RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
45 SealHandleScope shs(isolate);
46 DCHECK(args.length() == 0);
47 return isolate->heap()->ToBoolean(
48 isolate->concurrent_recompilation_enabled());
52 RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
53 HandleScope scope(isolate);
54 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
55 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
56 // The following two assertions are lifted from the DCHECKs inside
57 // JSFunction::MarkForOptimization().
58 RUNTIME_ASSERT(!function->shared()->is_generator());
59 RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
60 (function->code()->kind() == Code::FUNCTION &&
61 function->code()->optimizable()));
63 // If the function is optimized, just return.
64 if (function->IsOptimized()) return isolate->heap()->undefined_value();
66 function->MarkForOptimization();
68 Code* unoptimized = function->shared()->code();
69 if (args.length() == 2 && unoptimized->kind() == Code::FUNCTION) {
70 CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
71 if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("osr")) && FLAG_use_osr) {
72 // Start patching from the currently patched loop nesting level.
73 DCHECK(BackEdgeTable::Verify(isolate, unoptimized));
74 isolate->runtime_profiler()->AttemptOnStackReplacement(
75 *function, Code::kMaxLoopNestingMarker);
76 } else if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
77 isolate->concurrent_recompilation_enabled()) {
78 function->MarkForConcurrentOptimization();
82 return isolate->heap()->undefined_value();
86 RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
87 HandleScope scope(isolate);
88 DCHECK(args.length() == 1);
89 CONVERT_ARG_CHECKED(JSFunction, function, 0);
90 function->shared()->set_optimization_disabled(true);
91 return isolate->heap()->undefined_value();
95 RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
96 HandleScope scope(isolate);
97 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
98 if (!isolate->use_crankshaft()) {
99 return Smi::FromInt(4); // 4 == "never".
101 bool sync_with_compiler_thread = true;
102 if (args.length() == 2) {
103 CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
104 if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
105 sync_with_compiler_thread = false;
108 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
109 if (isolate->concurrent_recompilation_enabled() &&
110 sync_with_compiler_thread) {
111 while (function->IsInOptimizationQueue()) {
112 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
116 if (FLAG_always_opt) {
117 // We may have always opt, but that is more best-effort than a real
118 // promise, so we still say "no" if it is not optimized.
119 return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always".
120 : Smi::FromInt(2); // 2 == "no".
122 if (FLAG_deopt_every_n_times) {
123 return Smi::FromInt(6); // 6 == "maybe deopted".
125 if (function->IsOptimized() && function->code()->is_turbofanned()) {
126 return Smi::FromInt(7); // 7 == "TurboFan compiler".
128 return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
129 : Smi::FromInt(2); // 2 == "no".
133 RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
134 DCHECK(args.length() == 0);
135 RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
136 RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
137 isolate->optimizing_compiler_thread()->Unblock();
138 return isolate->heap()->undefined_value();
142 RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
143 HandleScope scope(isolate);
144 DCHECK(args.length() == 1);
145 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
146 return Smi::FromInt(function->shared()->opt_count());
150 RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
151 HandleScope scope(isolate);
152 DCHECK(args.length() == 1);
153 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
154 function->shared()->ClearTypeFeedbackInfo();
155 Code* unoptimized = function->shared()->code();
156 if (unoptimized->kind() == Code::FUNCTION) {
157 unoptimized->ClearInlineCaches();
159 return isolate->heap()->undefined_value();
163 RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
164 HandleScope scope(isolate);
165 DCHECK(args.length() == 0);
166 isolate->heap()->NotifyContextDisposed();
167 return isolate->heap()->undefined_value();
171 RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
172 SealHandleScope shs(isolate);
173 DCHECK(args.length() == 2 || args.length() == 3);
175 CONVERT_SMI_ARG_CHECKED(interval, 0);
176 CONVERT_SMI_ARG_CHECKED(timeout, 1);
177 isolate->heap()->set_allocation_timeout(timeout);
178 FLAG_gc_interval = interval;
179 if (args.length() == 3) {
180 // Enable/disable inline allocation if requested.
181 CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
182 if (inline_allocation) {
183 isolate->heap()->EnableInlineAllocation();
185 isolate->heap()->DisableInlineAllocation();
189 return isolate->heap()->undefined_value();
193 RUNTIME_FUNCTION(Runtime_DebugPrint) {
194 SealHandleScope shs(isolate);
195 DCHECK(args.length() == 1);
199 if (args[0]->IsString()) {
200 // If we have a string, assume it's a code "marker"
201 // and print some interesting cpu debugging info.
202 JavaScriptFrameIterator it(isolate);
203 JavaScriptFrame* frame = it.frame();
204 os << "fp = " << frame->fp() << ", sp = " << frame->sp()
205 << ", caller_sp = " << frame->caller_sp() << ": ";
207 os << "DebugPrint: ";
210 if (args[0]->IsHeapObject()) {
212 HeapObject::cast(args[0])->map()->Print(os);
215 // ShortPrint is available in release mode. Print is not.
216 os << Brief(args[0]);
220 return args[0]; // return TOS
224 RUNTIME_FUNCTION(Runtime_DebugTrace) {
225 SealHandleScope shs(isolate);
226 DCHECK(args.length() == 0);
227 isolate->PrintStack(stdout);
228 return isolate->heap()->undefined_value();
232 // This will not allocate (flatten the string), but it may run
233 // very slowly for very deeply nested ConsStrings. For debugging use only.
234 RUNTIME_FUNCTION(Runtime_GlobalPrint) {
235 SealHandleScope shs(isolate);
236 DCHECK(args.length() == 1);
238 CONVERT_ARG_CHECKED(String, string, 0);
239 StringCharacterStream stream(string);
240 while (stream.HasMore()) {
241 uint16_t character = stream.GetNext();
242 PrintF("%c", character);
248 RUNTIME_FUNCTION(Runtime_SystemBreak) {
249 // The code below doesn't create handles, but when breaking here in GDB
250 // having a handle scope might be useful.
251 HandleScope scope(isolate);
252 DCHECK(args.length() == 0);
253 base::OS::DebugBreak();
254 return isolate->heap()->undefined_value();
259 RUNTIME_FUNCTION(Runtime_SetFlags) {
260 SealHandleScope shs(isolate);
261 DCHECK(args.length() == 1);
262 CONVERT_ARG_CHECKED(String, arg, 0);
263 SmartArrayPointer<char> flags =
264 arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
265 FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
266 return isolate->heap()->undefined_value();
270 RUNTIME_FUNCTION(Runtime_Abort) {
271 SealHandleScope shs(isolate);
272 DCHECK(args.length() == 1);
273 CONVERT_SMI_ARG_CHECKED(message_id, 0);
274 const char* message =
275 GetBailoutReason(static_cast<BailoutReason>(message_id));
276 base::OS::PrintError("abort: %s\n", message);
277 isolate->PrintStack(stderr);
284 RUNTIME_FUNCTION(Runtime_AbortJS) {
285 HandleScope scope(isolate);
286 DCHECK(args.length() == 1);
287 CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
288 base::OS::PrintError("abort: %s\n", message->ToCString().get());
289 isolate->PrintStack(stderr);
296 RUNTIME_FUNCTION(Runtime_NativeScriptsCount) {
297 DCHECK(args.length() == 0);
298 return Smi::FromInt(Natives::GetBuiltinsCount());
302 // Returns V8 version as a string.
303 RUNTIME_FUNCTION(Runtime_GetV8Version) {
304 HandleScope scope(isolate);
305 DCHECK(args.length() == 0);
307 const char* version_string = v8::V8::GetVersion();
309 return *isolate->factory()->NewStringFromAsciiChecked(version_string);
313 static int StackSize(Isolate* isolate) {
315 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
320 static void PrintTransition(Isolate* isolate, Object* result) {
324 int n = StackSize(isolate);
326 PrintF("%4d:%*s", n, n, "");
328 PrintF("%4d:%*s", n, nmax, "...");
331 if (result == NULL) {
332 JavaScriptFrame::PrintTop(isolate, stdout, true, false);
337 result->ShortPrint();
343 RUNTIME_FUNCTION(Runtime_TraceEnter) {
344 SealHandleScope shs(isolate);
345 DCHECK(args.length() == 0);
346 PrintTransition(isolate, NULL);
347 return isolate->heap()->undefined_value();
351 RUNTIME_FUNCTION(Runtime_TraceExit) {
352 SealHandleScope shs(isolate);
353 DCHECK(args.length() == 1);
354 CONVERT_ARG_CHECKED(Object, obj, 0);
355 PrintTransition(isolate, obj);
356 return obj; // return TOS
360 RUNTIME_FUNCTION(Runtime_HaveSameMap) {
361 SealHandleScope shs(isolate);
362 DCHECK(args.length() == 2);
363 CONVERT_ARG_CHECKED(JSObject, obj1, 0);
364 CONVERT_ARG_CHECKED(JSObject, obj2, 1);
365 return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
369 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
370 RUNTIME_FUNCTION(Runtime_Has##Name) { \
371 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
372 return isolate->heap()->ToBoolean(obj->Has##Name()); \
375 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
376 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
377 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
378 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
379 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
380 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
381 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
382 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
383 // Properties test sitting with elements tests - not fooling anyone.
384 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
386 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
389 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
390 RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \
391 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
392 return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
395 TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
397 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
400 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
401 RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
402 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
403 return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
406 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
408 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
410 } // namespace v8::internal