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 assertion was lifted from the DCHECK inside
57 // JSFunction::MarkForOptimization().
58 RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
59 (function->code()->kind() == Code::FUNCTION &&
60 function->code()->optimizable()));
62 if (!isolate->use_crankshaft()) return isolate->heap()->undefined_value();
64 // If the function is already optimized, just return.
65 if (function->IsOptimized()) return isolate->heap()->undefined_value();
67 function->MarkForOptimization();
69 Code* unoptimized = function->shared()->code();
70 if (args.length() == 2 && unoptimized->kind() == Code::FUNCTION) {
71 CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
72 if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
73 isolate->concurrent_recompilation_enabled()) {
74 function->AttemptConcurrentOptimization();
78 return isolate->heap()->undefined_value();
82 RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
83 HandleScope scope(isolate);
84 RUNTIME_ASSERT(args.length() == 0);
85 Handle<JSFunction> function = Handle<JSFunction>::null();
88 // Find the JavaScript function on the top of the stack.
89 JavaScriptFrameIterator it(isolate);
91 if (it.frame()->is_java_script()) {
92 function = Handle<JSFunction>(it.frame()->function());
96 if (function.is_null()) return isolate->heap()->undefined_value();
99 // The following assertion was lifted from the DCHECK inside
100 // JSFunction::MarkForOptimization().
101 RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
102 (function->code()->kind() == Code::FUNCTION &&
103 function->code()->optimizable()));
105 if (!isolate->use_crankshaft()) return isolate->heap()->undefined_value();
107 // If the function is already optimized, just return.
108 if (function->IsOptimized()) return isolate->heap()->undefined_value();
110 Code* unoptimized = function->shared()->code();
111 if (unoptimized->kind() == Code::FUNCTION) {
112 DCHECK(BackEdgeTable::Verify(isolate, unoptimized));
113 isolate->runtime_profiler()->AttemptOnStackReplacement(
114 *function, Code::kMaxLoopNestingMarker);
117 return isolate->heap()->undefined_value();
121 RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
122 HandleScope scope(isolate);
123 DCHECK(args.length() == 1);
124 CONVERT_ARG_CHECKED(JSFunction, function, 0);
125 function->shared()->set_disable_optimization_reason(kOptimizationDisabled);
126 function->shared()->set_optimization_disabled(true);
127 return isolate->heap()->undefined_value();
131 RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
132 HandleScope scope(isolate);
133 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
134 if (!isolate->use_crankshaft()) {
135 return Smi::FromInt(4); // 4 == "never".
137 bool sync_with_compiler_thread = true;
138 if (args.length() == 2) {
139 CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
140 if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
141 sync_with_compiler_thread = false;
144 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
145 if (isolate->concurrent_recompilation_enabled() &&
146 sync_with_compiler_thread) {
147 while (function->IsInOptimizationQueue()) {
148 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
152 if (FLAG_always_opt) {
153 // We may have always opt, but that is more best-effort than a real
154 // promise, so we still say "no" if it is not optimized.
155 return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always".
156 : Smi::FromInt(2); // 2 == "no".
158 if (FLAG_deopt_every_n_times) {
159 return Smi::FromInt(6); // 6 == "maybe deopted".
161 if (function->IsOptimized() && function->code()->is_turbofanned()) {
162 return Smi::FromInt(7); // 7 == "TurboFan compiler".
164 return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
165 : Smi::FromInt(2); // 2 == "no".
169 RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
170 DCHECK(args.length() == 0);
171 RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
172 RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
173 isolate->optimizing_compiler_thread()->Unblock();
174 return isolate->heap()->undefined_value();
178 RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
179 HandleScope scope(isolate);
180 DCHECK(args.length() == 1);
181 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
182 return Smi::FromInt(function->shared()->opt_count());
186 RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
187 HandleScope scope(isolate);
188 DCHECK(args.length() == 1);
189 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
190 function->shared()->ClearTypeFeedbackInfo();
191 Code* unoptimized = function->shared()->code();
192 if (unoptimized->kind() == Code::FUNCTION) {
193 unoptimized->ClearInlineCaches();
195 return isolate->heap()->undefined_value();
199 RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
200 HandleScope scope(isolate);
201 DCHECK(args.length() == 0);
202 isolate->heap()->NotifyContextDisposed(true);
203 return isolate->heap()->undefined_value();
207 RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
208 SealHandleScope shs(isolate);
209 DCHECK(args.length() == 2 || args.length() == 3);
211 CONVERT_SMI_ARG_CHECKED(interval, 0);
212 CONVERT_SMI_ARG_CHECKED(timeout, 1);
213 isolate->heap()->set_allocation_timeout(timeout);
214 FLAG_gc_interval = interval;
215 if (args.length() == 3) {
216 // Enable/disable inline allocation if requested.
217 CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
218 if (inline_allocation) {
219 isolate->heap()->EnableInlineAllocation();
221 isolate->heap()->DisableInlineAllocation();
225 return isolate->heap()->undefined_value();
229 RUNTIME_FUNCTION(Runtime_DebugPrint) {
230 SealHandleScope shs(isolate);
231 DCHECK(args.length() == 1);
235 if (args[0]->IsString()) {
236 // If we have a string, assume it's a code "marker"
237 // and print some interesting cpu debugging info.
238 JavaScriptFrameIterator it(isolate);
239 JavaScriptFrame* frame = it.frame();
240 os << "fp = " << frame->fp() << ", sp = " << frame->sp()
241 << ", caller_sp = " << frame->caller_sp() << ": ";
243 os << "DebugPrint: ";
246 if (args[0]->IsHeapObject()) {
248 HeapObject::cast(args[0])->map()->Print(os);
251 // ShortPrint is available in release mode. Print is not.
252 os << Brief(args[0]);
256 return args[0]; // return TOS
260 RUNTIME_FUNCTION(Runtime_DebugTrace) {
261 SealHandleScope shs(isolate);
262 DCHECK(args.length() == 0);
263 isolate->PrintStack(stdout);
264 return isolate->heap()->undefined_value();
268 // This will not allocate (flatten the string), but it may run
269 // very slowly for very deeply nested ConsStrings. For debugging use only.
270 RUNTIME_FUNCTION(Runtime_GlobalPrint) {
271 SealHandleScope shs(isolate);
272 DCHECK(args.length() == 1);
274 CONVERT_ARG_CHECKED(String, string, 0);
275 StringCharacterStream stream(string);
276 while (stream.HasMore()) {
277 uint16_t character = stream.GetNext();
278 PrintF("%c", character);
284 RUNTIME_FUNCTION(Runtime_SystemBreak) {
285 // The code below doesn't create handles, but when breaking here in GDB
286 // having a handle scope might be useful.
287 HandleScope scope(isolate);
288 DCHECK(args.length() == 0);
289 base::OS::DebugBreak();
290 return isolate->heap()->undefined_value();
295 RUNTIME_FUNCTION(Runtime_SetFlags) {
296 SealHandleScope shs(isolate);
297 DCHECK(args.length() == 1);
298 CONVERT_ARG_CHECKED(String, arg, 0);
299 SmartArrayPointer<char> flags =
300 arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
301 FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
302 return isolate->heap()->undefined_value();
306 RUNTIME_FUNCTION(Runtime_Abort) {
307 SealHandleScope shs(isolate);
308 DCHECK(args.length() == 1);
309 CONVERT_SMI_ARG_CHECKED(message_id, 0);
310 const char* message =
311 GetBailoutReason(static_cast<BailoutReason>(message_id));
312 base::OS::PrintError("abort: %s\n", message);
313 isolate->PrintStack(stderr);
320 RUNTIME_FUNCTION(Runtime_AbortJS) {
321 HandleScope scope(isolate);
322 DCHECK(args.length() == 1);
323 CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
324 base::OS::PrintError("abort: %s\n", message->ToCString().get());
325 isolate->PrintStack(stderr);
332 RUNTIME_FUNCTION(Runtime_NativeScriptsCount) {
333 DCHECK(args.length() == 0);
334 return Smi::FromInt(Natives::GetBuiltinsCount());
338 // Returns V8 version as a string.
339 RUNTIME_FUNCTION(Runtime_GetV8Version) {
340 HandleScope scope(isolate);
341 DCHECK(args.length() == 0);
343 const char* version_string = v8::V8::GetVersion();
345 return *isolate->factory()->NewStringFromAsciiChecked(version_string);
349 static int StackSize(Isolate* isolate) {
351 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
356 static void PrintTransition(Isolate* isolate, Object* result) {
360 int n = StackSize(isolate);
362 PrintF("%4d:%*s", n, n, "");
364 PrintF("%4d:%*s", n, nmax, "...");
367 if (result == NULL) {
368 JavaScriptFrame::PrintTop(isolate, stdout, true, false);
373 result->ShortPrint();
379 RUNTIME_FUNCTION(Runtime_TraceEnter) {
380 SealHandleScope shs(isolate);
381 DCHECK(args.length() == 0);
382 PrintTransition(isolate, NULL);
383 return isolate->heap()->undefined_value();
387 RUNTIME_FUNCTION(Runtime_TraceExit) {
388 SealHandleScope shs(isolate);
389 DCHECK(args.length() == 1);
390 CONVERT_ARG_CHECKED(Object, obj, 0);
391 PrintTransition(isolate, obj);
392 return obj; // return TOS
396 RUNTIME_FUNCTION(Runtime_HaveSameMap) {
397 SealHandleScope shs(isolate);
398 DCHECK(args.length() == 2);
399 CONVERT_ARG_CHECKED(JSObject, obj1, 0);
400 CONVERT_ARG_CHECKED(JSObject, obj2, 1);
401 return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
405 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
406 RUNTIME_FUNCTION(Runtime_Has##Name) { \
407 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
408 return isolate->heap()->ToBoolean(obj->Has##Name()); \
411 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
412 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
413 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
414 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
415 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
416 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
417 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
418 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
419 // Properties test sitting with elements tests - not fooling anyone.
420 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
422 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
425 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
426 RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \
427 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
428 return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
431 TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
433 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
436 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
437 RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
438 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
439 return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
442 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
444 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
446 } // namespace v8::internal