blob: 5f27a609a6d934b6977875250ff7369cd30195fa [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// 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.
4
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/runtime/runtime-utils.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006
7#include "src/arguments.h"
8#include "src/deoptimizer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/frames-inl.h"
10#include "src/full-codegen/full-codegen.h"
11#include "src/snapshot/natives.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012
13namespace v8 {
14namespace internal {
15
16RUNTIME_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();
21
22 // TODO(turbofan): Deoptimization is not supported yet.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023 if (function->code()->is_turbofanned() &&
24 function->shared()->asm_function() && !FLAG_turbo_asm_deoptimization) {
25 return isolate->heap()->undefined_value();
26 }
27
28 Deoptimizer::DeoptimizeFunction(*function);
29
30 return isolate->heap()->undefined_value();
31}
32
33
34RUNTIME_FUNCTION(Runtime_DeoptimizeNow) {
35 HandleScope scope(isolate);
36 DCHECK(args.length() == 0);
37
38 Handle<JSFunction> function;
39
40 // If the argument is 'undefined', deoptimize the topmost
41 // function.
42 JavaScriptFrameIterator it(isolate);
43 while (!it.done()) {
44 if (it.frame()->is_java_script()) {
45 function = Handle<JSFunction>(it.frame()->function());
46 break;
47 }
48 }
49 if (function.is_null()) return isolate->heap()->undefined_value();
50
51 if (!function->IsOptimized()) return isolate->heap()->undefined_value();
52
53 // TODO(turbofan): Deoptimization is not supported yet.
54 if (function->code()->is_turbofanned() &&
55 function->shared()->asm_function() && !FLAG_turbo_asm_deoptimization) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056 return isolate->heap()->undefined_value();
57 }
58
59 Deoptimizer::DeoptimizeFunction(*function);
60
61 return isolate->heap()->undefined_value();
62}
63
64
65RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
66 SealHandleScope shs(isolate);
67 DCHECK(args.length() == 0);
68#if defined(USE_SIMULATOR)
69 return isolate->heap()->true_value();
70#else
71 return isolate->heap()->false_value();
72#endif
73}
74
75
76RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
77 SealHandleScope shs(isolate);
78 DCHECK(args.length() == 0);
79 return isolate->heap()->ToBoolean(
80 isolate->concurrent_recompilation_enabled());
81}
82
83
84RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
85 HandleScope scope(isolate);
86 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
87 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 // The following assertion was lifted from the DCHECK inside
Emily Bernierd0a1eb72015-03-24 16:35:39 -040089 // JSFunction::MarkForOptimization().
Emily Bernierd0a1eb72015-03-24 16:35:39 -040090 RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
91 (function->code()->kind() == Code::FUNCTION &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 !function->shared()->optimization_disabled()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040093
94 // If the function is already optimized, just return.
95 if (function->IsOptimized()) return isolate->heap()->undefined_value();
96
Emily Bernierd0a1eb72015-03-24 16:35:39 -040097 function->MarkForOptimization();
98
99 Code* unoptimized = function->shared()->code();
100 if (args.length() == 2 && unoptimized->kind() == Code::FUNCTION) {
101 CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
103 isolate->concurrent_recompilation_enabled()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400104 function->AttemptConcurrentOptimization();
105 }
106 }
107
108 return isolate->heap()->undefined_value();
109}
110
111
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
113 HandleScope scope(isolate);
114 RUNTIME_ASSERT(args.length() == 0 || args.length() == 1);
115 Handle<JSFunction> function = Handle<JSFunction>::null();
116
117 if (args.length() == 0) {
118 // Find the JavaScript function on the top of the stack.
119 JavaScriptFrameIterator it(isolate);
120 while (!it.done()) {
121 if (it.frame()->is_java_script()) {
122 function = Handle<JSFunction>(it.frame()->function());
123 break;
124 }
125 }
126 if (function.is_null()) return isolate->heap()->undefined_value();
127 } else {
128 // Function was passed as an argument.
129 CONVERT_ARG_HANDLE_CHECKED(JSFunction, arg, 0);
130 function = arg;
131 }
132
133 // The following assertion was lifted from the DCHECK inside
134 // JSFunction::MarkForOptimization().
135 RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
136 !function->shared()->optimization_disabled());
137
138 // If the function is already optimized, just return.
139 if (function->IsOptimized()) return isolate->heap()->undefined_value();
140
141 Code* unoptimized = function->shared()->code();
142 if (unoptimized->kind() == Code::FUNCTION) {
143 DCHECK(BackEdgeTable::Verify(isolate, unoptimized));
144 isolate->runtime_profiler()->AttemptOnStackReplacement(
145 *function, Code::kMaxLoopNestingMarker);
146 }
147
148 return isolate->heap()->undefined_value();
149}
150
151
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400152RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
153 HandleScope scope(isolate);
154 DCHECK(args.length() == 1);
155 CONVERT_ARG_CHECKED(JSFunction, function, 0);
156 function->shared()->set_disable_optimization_reason(kOptimizationDisabled);
157 function->shared()->set_optimization_disabled(true);
158 return isolate->heap()->undefined_value();
159}
160
161
162RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
163 HandleScope scope(isolate);
164 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
165 if (!isolate->use_crankshaft()) {
166 return Smi::FromInt(4); // 4 == "never".
167 }
168 bool sync_with_compiler_thread = true;
169 if (args.length() == 2) {
170 CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
171 if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
172 sync_with_compiler_thread = false;
173 }
174 }
175 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
176 if (isolate->concurrent_recompilation_enabled() &&
177 sync_with_compiler_thread) {
178 while (function->IsInOptimizationQueue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 isolate->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
180 base::OS::Sleep(base::TimeDelta::FromMilliseconds(50));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400181 }
182 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 if (FLAG_always_opt || FLAG_prepare_always_opt) {
184 // With --always-opt, optimization status expectations might not
185 // match up, so just return a sentinel.
186 return Smi::FromInt(3); // 3 == "always".
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400187 }
188 if (FLAG_deopt_every_n_times) {
189 return Smi::FromInt(6); // 6 == "maybe deopted".
190 }
191 if (function->IsOptimized() && function->code()->is_turbofanned()) {
192 return Smi::FromInt(7); // 7 == "TurboFan compiler".
193 }
194 return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
195 : Smi::FromInt(2); // 2 == "no".
196}
197
198
199RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
200 DCHECK(args.length() == 0);
201 RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
202 RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 isolate->optimizing_compile_dispatcher()->Unblock();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400204 return isolate->heap()->undefined_value();
205}
206
207
208RUNTIME_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());
213}
214
215
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216RUNTIME_FUNCTION(Runtime_GetUndetectable) {
217 HandleScope scope(isolate);
218 DCHECK(args.length() == 0);
219 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
220
221 Local<v8::ObjectTemplate> desc = v8::ObjectTemplate::New(v8_isolate);
222 desc->MarkAsUndetectable();
223 Local<v8::Object> obj;
224 if (!desc->NewInstance(v8_isolate->GetCurrentContext()).ToLocal(&obj)) {
225 return nullptr;
226 }
227 return *Utils::OpenHandle(*obj);
228}
229
230
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400231RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
232 HandleScope scope(isolate);
233 DCHECK(args.length() == 1);
234 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
235 function->shared()->ClearTypeFeedbackInfo();
236 Code* unoptimized = function->shared()->code();
237 if (unoptimized->kind() == Code::FUNCTION) {
238 unoptimized->ClearInlineCaches();
239 }
240 return isolate->heap()->undefined_value();
241}
242
243
244RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
245 HandleScope scope(isolate);
246 DCHECK(args.length() == 0);
247 isolate->heap()->NotifyContextDisposed(true);
248 return isolate->heap()->undefined_value();
249}
250
251
252RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
253 SealHandleScope shs(isolate);
254 DCHECK(args.length() == 2 || args.length() == 3);
255#ifdef DEBUG
256 CONVERT_SMI_ARG_CHECKED(interval, 0);
257 CONVERT_SMI_ARG_CHECKED(timeout, 1);
258 isolate->heap()->set_allocation_timeout(timeout);
259 FLAG_gc_interval = interval;
260 if (args.length() == 3) {
261 // Enable/disable inline allocation if requested.
262 CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
263 if (inline_allocation) {
264 isolate->heap()->EnableInlineAllocation();
265 } else {
266 isolate->heap()->DisableInlineAllocation();
267 }
268 }
269#endif
270 return isolate->heap()->undefined_value();
271}
272
273
274RUNTIME_FUNCTION(Runtime_DebugPrint) {
275 SealHandleScope shs(isolate);
276 DCHECK(args.length() == 1);
277
278 OFStream os(stdout);
279#ifdef DEBUG
280 if (args[0]->IsString()) {
281 // If we have a string, assume it's a code "marker"
282 // and print some interesting cpu debugging info.
283 JavaScriptFrameIterator it(isolate);
284 JavaScriptFrame* frame = it.frame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 os << "fp = " << static_cast<void*>(frame->fp())
286 << ", sp = " << static_cast<void*>(frame->sp())
287 << ", caller_sp = " << static_cast<void*>(frame->caller_sp()) << ": ";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400288 } else {
289 os << "DebugPrint: ";
290 }
291 args[0]->Print(os);
292 if (args[0]->IsHeapObject()) {
293 os << "\n";
294 HeapObject::cast(args[0])->map()->Print(os);
295 }
296#else
297 // ShortPrint is available in release mode. Print is not.
298 os << Brief(args[0]);
299#endif
300 os << std::endl;
301
302 return args[0]; // return TOS
303}
304
305
306RUNTIME_FUNCTION(Runtime_DebugTrace) {
307 SealHandleScope shs(isolate);
308 DCHECK(args.length() == 0);
309 isolate->PrintStack(stdout);
310 return isolate->heap()->undefined_value();
311}
312
313
314// This will not allocate (flatten the string), but it may run
315// very slowly for very deeply nested ConsStrings. For debugging use only.
316RUNTIME_FUNCTION(Runtime_GlobalPrint) {
317 SealHandleScope shs(isolate);
318 DCHECK(args.length() == 1);
319
320 CONVERT_ARG_CHECKED(String, string, 0);
321 StringCharacterStream stream(string);
322 while (stream.HasMore()) {
323 uint16_t character = stream.GetNext();
324 PrintF("%c", character);
325 }
326 return string;
327}
328
329
330RUNTIME_FUNCTION(Runtime_SystemBreak) {
331 // The code below doesn't create handles, but when breaking here in GDB
332 // having a handle scope might be useful.
333 HandleScope scope(isolate);
334 DCHECK(args.length() == 0);
335 base::OS::DebugBreak();
336 return isolate->heap()->undefined_value();
337}
338
339
340// Sets a v8 flag.
341RUNTIME_FUNCTION(Runtime_SetFlags) {
342 SealHandleScope shs(isolate);
343 DCHECK(args.length() == 1);
344 CONVERT_ARG_CHECKED(String, arg, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345 base::SmartArrayPointer<char> flags =
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400346 arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
347 FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
348 return isolate->heap()->undefined_value();
349}
350
351
352RUNTIME_FUNCTION(Runtime_Abort) {
353 SealHandleScope shs(isolate);
354 DCHECK(args.length() == 1);
355 CONVERT_SMI_ARG_CHECKED(message_id, 0);
356 const char* message =
357 GetBailoutReason(static_cast<BailoutReason>(message_id));
358 base::OS::PrintError("abort: %s\n", message);
359 isolate->PrintStack(stderr);
360 base::OS::Abort();
361 UNREACHABLE();
362 return NULL;
363}
364
365
366RUNTIME_FUNCTION(Runtime_AbortJS) {
367 HandleScope scope(isolate);
368 DCHECK(args.length() == 1);
369 CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
370 base::OS::PrintError("abort: %s\n", message->ToCString().get());
371 isolate->PrintStack(stderr);
372 base::OS::Abort();
373 UNREACHABLE();
374 return NULL;
375}
376
377
378RUNTIME_FUNCTION(Runtime_NativeScriptsCount) {
379 DCHECK(args.length() == 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100380 return Smi::FromInt(Natives::GetBuiltinsCount());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400381}
382
383
384// Returns V8 version as a string.
385RUNTIME_FUNCTION(Runtime_GetV8Version) {
386 HandleScope scope(isolate);
387 DCHECK(args.length() == 0);
388
389 const char* version_string = v8::V8::GetVersion();
390
391 return *isolate->factory()->NewStringFromAsciiChecked(version_string);
392}
393
394
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395RUNTIME_FUNCTION(Runtime_DisassembleFunction) {
396 HandleScope scope(isolate);
397#ifdef DEBUG
398 DCHECK(args.length() == 1);
399 // Get the function and make sure it is compiled.
400 CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
401 if (!Compiler::Compile(func, KEEP_EXCEPTION)) {
402 return isolate->heap()->exception();
403 }
404 OFStream os(stdout);
405 func->code()->Print(os);
406 os << std::endl;
407#endif // DEBUG
408 return isolate->heap()->undefined_value();
409}
410
Ben Murdoch097c5b22016-05-18 11:27:45 +0100411namespace {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412
Ben Murdoch097c5b22016-05-18 11:27:45 +0100413int StackSize(Isolate* isolate) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400414 int n = 0;
415 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
416 return n;
417}
418
Ben Murdoch097c5b22016-05-18 11:27:45 +0100419void PrintIndentation(Isolate* isolate) {
420 const int nmax = 80;
421 int n = StackSize(isolate);
422 if (n <= nmax) {
423 PrintF("%4d:%*s", n, n, "");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400424 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100425 PrintF("%4d:%*s", n, nmax, "...");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400426 }
427}
428
Ben Murdoch097c5b22016-05-18 11:27:45 +0100429} // namespace
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400430
431RUNTIME_FUNCTION(Runtime_TraceEnter) {
432 SealHandleScope shs(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100433 DCHECK_EQ(0, args.length());
434 PrintIndentation(isolate);
435 JavaScriptFrame::PrintTop(isolate, stdout, true, false);
436 PrintF(" {\n");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400437 return isolate->heap()->undefined_value();
438}
439
440
441RUNTIME_FUNCTION(Runtime_TraceExit) {
442 SealHandleScope shs(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100443 DCHECK_EQ(1, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400444 CONVERT_ARG_CHECKED(Object, obj, 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100445 PrintIndentation(isolate);
446 PrintF("} -> ");
447 obj->ShortPrint();
448 PrintF("\n");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400449 return obj; // return TOS
450}
451
Ben Murdoch097c5b22016-05-18 11:27:45 +0100452RUNTIME_FUNCTION(Runtime_TraceTailCall) {
453 SealHandleScope shs(isolate);
454 DCHECK_EQ(0, args.length());
455 PrintIndentation(isolate);
456 PrintF("} -> tail call ->\n");
457 return isolate->heap()->undefined_value();
458}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459
460RUNTIME_FUNCTION(Runtime_HaveSameMap) {
461 SealHandleScope shs(isolate);
462 DCHECK(args.length() == 2);
463 CONVERT_ARG_CHECKED(JSObject, obj1, 0);
464 CONVERT_ARG_CHECKED(JSObject, obj2, 1);
465 return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
466}
467
468
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469RUNTIME_FUNCTION(Runtime_InNewSpace) {
470 SealHandleScope shs(isolate);
471 DCHECK(args.length() == 1);
472 CONVERT_ARG_CHECKED(Object, obj, 0);
473 return isolate->heap()->ToBoolean(isolate->heap()->InNewSpace(obj));
474}
475
476
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400477#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
478 RUNTIME_FUNCTION(Runtime_Has##Name) { \
479 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
480 return isolate->heap()->ToBoolean(obj->Has##Name()); \
481 }
482
483ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
484ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
485ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
486ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
487ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
488ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
489ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FixedTypedArrayElements)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400491// Properties test sitting with elements tests - not fooling anyone.
492ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
493
494#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
495
496
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400497#define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
498 RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
499 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
500 return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
501 }
502
503TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
504
505#undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506} // namespace internal
507} // namespace v8