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/runtime/runtime-utils.h"
11 #include "src/snapshot/natives.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_DeoptimizeNow) {
34 HandleScope scope(isolate);
35 DCHECK(args.length() == 0);
37 Handle<JSFunction> function;
39 // If the argument is 'undefined', deoptimize the topmost
41 JavaScriptFrameIterator it(isolate);
43 if (it.frame()->is_java_script()) {
44 function = Handle<JSFunction>(it.frame()->function());
48 if (function.is_null()) return isolate->heap()->undefined_value();
50 if (!function->IsOptimized()) return isolate->heap()->undefined_value();
52 // TODO(turbofan): Deoptimization is not supported yet.
53 if (function->code()->is_turbofanned() && !FLAG_turbo_deoptimization) {
54 return isolate->heap()->undefined_value();
57 Deoptimizer::DeoptimizeFunction(*function);
59 return isolate->heap()->undefined_value();
63 RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
64 SealHandleScope shs(isolate);
65 DCHECK(args.length() == 0);
66 #if defined(USE_SIMULATOR)
67 return isolate->heap()->true_value();
69 return isolate->heap()->false_value();
74 RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
75 SealHandleScope shs(isolate);
76 DCHECK(args.length() == 0);
77 return isolate->heap()->ToBoolean(
78 isolate->concurrent_recompilation_enabled());
82 RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
83 HandleScope scope(isolate);
84 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
85 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
86 // The following assertion was lifted from the DCHECK inside
87 // JSFunction::MarkForOptimization().
88 RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
89 (function->code()->kind() == Code::FUNCTION &&
90 function->code()->optimizable()));
92 // If the function is already optimized, just return.
93 if (function->IsOptimized()) return isolate->heap()->undefined_value();
95 function->MarkForOptimization();
97 Code* unoptimized = function->shared()->code();
98 if (args.length() == 2 && unoptimized->kind() == Code::FUNCTION) {
99 CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
100 if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
101 isolate->concurrent_recompilation_enabled()) {
102 function->AttemptConcurrentOptimization();
106 return isolate->heap()->undefined_value();
110 RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
111 HandleScope scope(isolate);
112 RUNTIME_ASSERT(args.length() == 0 || args.length() == 1);
113 Handle<JSFunction> function = Handle<JSFunction>::null();
115 if (args.length() == 0) {
116 // Find the JavaScript function on the top of the stack.
117 JavaScriptFrameIterator it(isolate);
119 if (it.frame()->is_java_script()) {
120 function = Handle<JSFunction>(it.frame()->function());
124 if (function.is_null()) return isolate->heap()->undefined_value();
126 // Function was passed as an argument.
127 CONVERT_ARG_HANDLE_CHECKED(JSFunction, arg, 0);
131 // The following assertion was lifted from the DCHECK inside
132 // JSFunction::MarkForOptimization().
133 RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
134 (function->code()->kind() == Code::FUNCTION &&
135 function->code()->optimizable()));
137 // If the function is already optimized, just return.
138 if (function->IsOptimized()) return isolate->heap()->undefined_value();
140 Code* unoptimized = function->shared()->code();
141 if (unoptimized->kind() == Code::FUNCTION) {
142 DCHECK(BackEdgeTable::Verify(isolate, unoptimized));
143 isolate->runtime_profiler()->AttemptOnStackReplacement(
144 *function, Code::kMaxLoopNestingMarker);
147 return isolate->heap()->undefined_value();
151 RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
152 HandleScope scope(isolate);
153 DCHECK(args.length() == 1);
154 CONVERT_ARG_CHECKED(JSFunction, function, 0);
155 function->shared()->set_disable_optimization_reason(kOptimizationDisabled);
156 function->shared()->set_optimization_disabled(true);
157 return isolate->heap()->undefined_value();
161 RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
162 HandleScope scope(isolate);
163 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
164 if (!isolate->use_crankshaft()) {
165 return Smi::FromInt(4); // 4 == "never".
167 bool sync_with_compiler_thread = true;
168 if (args.length() == 2) {
169 CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
170 if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
171 sync_with_compiler_thread = false;
174 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
175 if (isolate->concurrent_recompilation_enabled() &&
176 sync_with_compiler_thread) {
177 while (function->IsInOptimizationQueue()) {
178 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
182 if (FLAG_always_opt) {
183 // We may have always opt, but that is more best-effort than a real
184 // promise, so we still say "no" if it is not optimized.
185 return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always".
186 : Smi::FromInt(2); // 2 == "no".
188 if (FLAG_deopt_every_n_times) {
189 return Smi::FromInt(6); // 6 == "maybe deopted".
191 if (function->IsOptimized() && function->code()->is_turbofanned()) {
192 return Smi::FromInt(7); // 7 == "TurboFan compiler".
194 return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
195 : Smi::FromInt(2); // 2 == "no".
199 RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
200 DCHECK(args.length() == 0);
201 RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
202 RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
203 isolate->optimizing_compiler_thread()->Unblock();
204 return isolate->heap()->undefined_value();
208 RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
209 HandleScope scope(isolate);
210 DCHECK(args.length() == 1);
211 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
212 return Smi::FromInt(function->shared()->opt_count());
216 RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
217 HandleScope scope(isolate);
218 DCHECK(args.length() == 1);
219 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
220 function->shared()->ClearTypeFeedbackInfo();
221 Code* unoptimized = function->shared()->code();
222 if (unoptimized->kind() == Code::FUNCTION) {
223 unoptimized->ClearInlineCaches();
225 return isolate->heap()->undefined_value();
229 RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
230 HandleScope scope(isolate);
231 DCHECK(args.length() == 0);
232 isolate->heap()->NotifyContextDisposed(true);
233 return isolate->heap()->undefined_value();
237 RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
238 SealHandleScope shs(isolate);
239 DCHECK(args.length() == 2 || args.length() == 3);
241 CONVERT_SMI_ARG_CHECKED(interval, 0);
242 CONVERT_SMI_ARG_CHECKED(timeout, 1);
243 isolate->heap()->set_allocation_timeout(timeout);
244 FLAG_gc_interval = interval;
245 if (args.length() == 3) {
246 // Enable/disable inline allocation if requested.
247 CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
248 if (inline_allocation) {
249 isolate->heap()->EnableInlineAllocation();
251 isolate->heap()->DisableInlineAllocation();
255 return isolate->heap()->undefined_value();
259 RUNTIME_FUNCTION(Runtime_DebugPrint) {
260 SealHandleScope shs(isolate);
261 DCHECK(args.length() == 1);
265 if (args[0]->IsString()) {
266 // If we have a string, assume it's a code "marker"
267 // and print some interesting cpu debugging info.
268 JavaScriptFrameIterator it(isolate);
269 JavaScriptFrame* frame = it.frame();
270 os << "fp = " << frame->fp() << ", sp = " << frame->sp()
271 << ", caller_sp = " << frame->caller_sp() << ": ";
273 os << "DebugPrint: ";
276 if (args[0]->IsHeapObject()) {
278 HeapObject::cast(args[0])->map()->Print(os);
281 // ShortPrint is available in release mode. Print is not.
282 os << Brief(args[0]);
286 return args[0]; // return TOS
290 RUNTIME_FUNCTION(Runtime_DebugTrace) {
291 SealHandleScope shs(isolate);
292 DCHECK(args.length() == 0);
293 isolate->PrintStack(stdout);
294 return isolate->heap()->undefined_value();
298 // This will not allocate (flatten the string), but it may run
299 // very slowly for very deeply nested ConsStrings. For debugging use only.
300 RUNTIME_FUNCTION(Runtime_GlobalPrint) {
301 SealHandleScope shs(isolate);
302 DCHECK(args.length() == 1);
304 CONVERT_ARG_CHECKED(String, string, 0);
305 StringCharacterStream stream(string);
306 while (stream.HasMore()) {
307 uint16_t character = stream.GetNext();
308 PrintF("%c", character);
314 RUNTIME_FUNCTION(Runtime_SystemBreak) {
315 // The code below doesn't create handles, but when breaking here in GDB
316 // having a handle scope might be useful.
317 HandleScope scope(isolate);
318 DCHECK(args.length() == 0);
319 base::OS::DebugBreak();
320 return isolate->heap()->undefined_value();
325 RUNTIME_FUNCTION(Runtime_SetFlags) {
326 SealHandleScope shs(isolate);
327 DCHECK(args.length() == 1);
328 CONVERT_ARG_CHECKED(String, arg, 0);
329 SmartArrayPointer<char> flags =
330 arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
331 FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
332 return isolate->heap()->undefined_value();
336 RUNTIME_FUNCTION(Runtime_Abort) {
337 SealHandleScope shs(isolate);
338 DCHECK(args.length() == 1);
339 CONVERT_SMI_ARG_CHECKED(message_id, 0);
340 const char* message =
341 GetBailoutReason(static_cast<BailoutReason>(message_id));
342 base::OS::PrintError("abort: %s\n", message);
343 isolate->PrintStack(stderr);
350 RUNTIME_FUNCTION(Runtime_AbortJS) {
351 HandleScope scope(isolate);
352 DCHECK(args.length() == 1);
353 CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
354 base::OS::PrintError("abort: %s\n", message->ToCString().get());
355 isolate->PrintStack(stderr);
362 RUNTIME_FUNCTION(Runtime_NativeScriptsCount) {
363 DCHECK(args.length() == 0);
364 return Smi::FromInt(Natives::GetBuiltinsCount());
368 // Returns V8 version as a string.
369 RUNTIME_FUNCTION(Runtime_GetV8Version) {
370 HandleScope scope(isolate);
371 DCHECK(args.length() == 0);
373 const char* version_string = v8::V8::GetVersion();
375 return *isolate->factory()->NewStringFromAsciiChecked(version_string);
379 RUNTIME_FUNCTION(Runtime_DisassembleFunction) {
380 HandleScope scope(isolate);
382 DCHECK(args.length() == 1);
383 // Get the function and make sure it is compiled.
384 CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
385 if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
386 return isolate->heap()->exception();
389 func->code()->Print(os);
392 return isolate->heap()->undefined_value();
396 static int StackSize(Isolate* isolate) {
398 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
403 static void PrintTransition(Isolate* isolate, Object* result) {
407 int n = StackSize(isolate);
409 PrintF("%4d:%*s", n, n, "");
411 PrintF("%4d:%*s", n, nmax, "...");
414 if (result == NULL) {
415 JavaScriptFrame::PrintTop(isolate, stdout, true, false);
420 result->ShortPrint();
426 RUNTIME_FUNCTION(Runtime_TraceEnter) {
427 SealHandleScope shs(isolate);
428 DCHECK(args.length() == 0);
429 PrintTransition(isolate, NULL);
430 return isolate->heap()->undefined_value();
434 RUNTIME_FUNCTION(Runtime_TraceExit) {
435 SealHandleScope shs(isolate);
436 DCHECK(args.length() == 1);
437 CONVERT_ARG_CHECKED(Object, obj, 0);
438 PrintTransition(isolate, obj);
439 return obj; // return TOS
443 RUNTIME_FUNCTION(Runtime_HaveSameMap) {
444 SealHandleScope shs(isolate);
445 DCHECK(args.length() == 2);
446 CONVERT_ARG_CHECKED(JSObject, obj1, 0);
447 CONVERT_ARG_CHECKED(JSObject, obj2, 1);
448 return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
452 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
453 RUNTIME_FUNCTION(Runtime_Has##Name) { \
454 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
455 return isolate->heap()->ToBoolean(obj->Has##Name()); \
458 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
459 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
460 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
461 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
462 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
463 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
464 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
465 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
466 // Properties test sitting with elements tests - not fooling anyone.
467 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
469 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
472 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
473 RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \
474 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
475 return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
478 TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
480 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
483 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
484 RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
485 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
486 return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
489 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
491 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
493 } // namespace v8::internal