blob: b4b90e2c5824463d548bc2816333caee7f8314f0 [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
5#include "src/v8.h"
6
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"
12
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.
23 if (function->code()->is_turbofanned() && !FLAG_turbo_deoptimization) {
24 return isolate->heap()->undefined_value();
25 }
26
27 Deoptimizer::DeoptimizeFunction(*function);
28
29 return isolate->heap()->undefined_value();
30}
31
32
33RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
34 SealHandleScope shs(isolate);
35 DCHECK(args.length() == 0);
36#if defined(USE_SIMULATOR)
37 return isolate->heap()->true_value();
38#else
39 return isolate->heap()->false_value();
40#endif
41}
42
43
44RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
45 SealHandleScope shs(isolate);
46 DCHECK(args.length() == 0);
47 return isolate->heap()->ToBoolean(
48 isolate->concurrent_recompilation_enabled());
49}
50
51
52RUNTIME_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()));
62
63 if (!isolate->use_crankshaft()) return isolate->heap()->undefined_value();
64
65 // If the function is already optimized, just return.
66 if (function->IsOptimized()) return isolate->heap()->undefined_value();
67
68 // If the function cannot optimized, just return.
69 if (function->shared()->optimization_disabled()) {
70 return isolate->heap()->undefined_value();
71 }
72
73 function->MarkForOptimization();
74
75 Code* unoptimized = function->shared()->code();
76 if (args.length() == 2 && unoptimized->kind() == Code::FUNCTION) {
77 CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
78 if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("osr")) && FLAG_use_osr) {
79 // Start patching from the currently patched loop nesting level.
80 DCHECK(BackEdgeTable::Verify(isolate, unoptimized));
81 isolate->runtime_profiler()->AttemptOnStackReplacement(
82 *function, Code::kMaxLoopNestingMarker);
83 } else if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
84 isolate->concurrent_recompilation_enabled()) {
85 function->AttemptConcurrentOptimization();
86 }
87 }
88
89 return isolate->heap()->undefined_value();
90}
91
92
93RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
94 HandleScope scope(isolate);
95 DCHECK(args.length() == 1);
96 CONVERT_ARG_CHECKED(JSFunction, function, 0);
97 function->shared()->set_disable_optimization_reason(kOptimizationDisabled);
98 function->shared()->set_optimization_disabled(true);
99 return isolate->heap()->undefined_value();
100}
101
102
103RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
104 HandleScope scope(isolate);
105 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
106 if (!isolate->use_crankshaft()) {
107 return Smi::FromInt(4); // 4 == "never".
108 }
109 bool sync_with_compiler_thread = true;
110 if (args.length() == 2) {
111 CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
112 if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
113 sync_with_compiler_thread = false;
114 }
115 }
116 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
117 if (isolate->concurrent_recompilation_enabled() &&
118 sync_with_compiler_thread) {
119 while (function->IsInOptimizationQueue()) {
120 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
121 base::OS::Sleep(50);
122 }
123 }
124 if (FLAG_always_opt) {
125 // We may have always opt, but that is more best-effort than a real
126 // promise, so we still say "no" if it is not optimized.
127 return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always".
128 : Smi::FromInt(2); // 2 == "no".
129 }
130 if (FLAG_deopt_every_n_times) {
131 return Smi::FromInt(6); // 6 == "maybe deopted".
132 }
133 if (function->IsOptimized() && function->code()->is_turbofanned()) {
134 return Smi::FromInt(7); // 7 == "TurboFan compiler".
135 }
136 return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
137 : Smi::FromInt(2); // 2 == "no".
138}
139
140
141RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
142 DCHECK(args.length() == 0);
143 RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
144 RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
145 isolate->optimizing_compiler_thread()->Unblock();
146 return isolate->heap()->undefined_value();
147}
148
149
150RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
151 HandleScope scope(isolate);
152 DCHECK(args.length() == 1);
153 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
154 return Smi::FromInt(function->shared()->opt_count());
155}
156
157
158RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
159 HandleScope scope(isolate);
160 DCHECK(args.length() == 1);
161 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
162 function->shared()->ClearTypeFeedbackInfo();
163 Code* unoptimized = function->shared()->code();
164 if (unoptimized->kind() == Code::FUNCTION) {
165 unoptimized->ClearInlineCaches();
166 }
167 return isolate->heap()->undefined_value();
168}
169
170
171RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
172 HandleScope scope(isolate);
173 DCHECK(args.length() == 0);
174 isolate->heap()->NotifyContextDisposed(true);
175 return isolate->heap()->undefined_value();
176}
177
178
179RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
180 SealHandleScope shs(isolate);
181 DCHECK(args.length() == 2 || args.length() == 3);
182#ifdef DEBUG
183 CONVERT_SMI_ARG_CHECKED(interval, 0);
184 CONVERT_SMI_ARG_CHECKED(timeout, 1);
185 isolate->heap()->set_allocation_timeout(timeout);
186 FLAG_gc_interval = interval;
187 if (args.length() == 3) {
188 // Enable/disable inline allocation if requested.
189 CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
190 if (inline_allocation) {
191 isolate->heap()->EnableInlineAllocation();
192 } else {
193 isolate->heap()->DisableInlineAllocation();
194 }
195 }
196#endif
197 return isolate->heap()->undefined_value();
198}
199
200
201RUNTIME_FUNCTION(Runtime_DebugPrint) {
202 SealHandleScope shs(isolate);
203 DCHECK(args.length() == 1);
204
205 OFStream os(stdout);
206#ifdef DEBUG
207 if (args[0]->IsString()) {
208 // If we have a string, assume it's a code "marker"
209 // and print some interesting cpu debugging info.
210 JavaScriptFrameIterator it(isolate);
211 JavaScriptFrame* frame = it.frame();
212 os << "fp = " << frame->fp() << ", sp = " << frame->sp()
213 << ", caller_sp = " << frame->caller_sp() << ": ";
214 } else {
215 os << "DebugPrint: ";
216 }
217 args[0]->Print(os);
218 if (args[0]->IsHeapObject()) {
219 os << "\n";
220 HeapObject::cast(args[0])->map()->Print(os);
221 }
222#else
223 // ShortPrint is available in release mode. Print is not.
224 os << Brief(args[0]);
225#endif
226 os << std::endl;
227
228 return args[0]; // return TOS
229}
230
231
232RUNTIME_FUNCTION(Runtime_DebugTrace) {
233 SealHandleScope shs(isolate);
234 DCHECK(args.length() == 0);
235 isolate->PrintStack(stdout);
236 return isolate->heap()->undefined_value();
237}
238
239
240// This will not allocate (flatten the string), but it may run
241// very slowly for very deeply nested ConsStrings. For debugging use only.
242RUNTIME_FUNCTION(Runtime_GlobalPrint) {
243 SealHandleScope shs(isolate);
244 DCHECK(args.length() == 1);
245
246 CONVERT_ARG_CHECKED(String, string, 0);
247 StringCharacterStream stream(string);
248 while (stream.HasMore()) {
249 uint16_t character = stream.GetNext();
250 PrintF("%c", character);
251 }
252 return string;
253}
254
255
256RUNTIME_FUNCTION(Runtime_SystemBreak) {
257 // The code below doesn't create handles, but when breaking here in GDB
258 // having a handle scope might be useful.
259 HandleScope scope(isolate);
260 DCHECK(args.length() == 0);
261 base::OS::DebugBreak();
262 return isolate->heap()->undefined_value();
263}
264
265
266// Sets a v8 flag.
267RUNTIME_FUNCTION(Runtime_SetFlags) {
268 SealHandleScope shs(isolate);
269 DCHECK(args.length() == 1);
270 CONVERT_ARG_CHECKED(String, arg, 0);
271 SmartArrayPointer<char> flags =
272 arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
273 FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
274 return isolate->heap()->undefined_value();
275}
276
277
278RUNTIME_FUNCTION(Runtime_Abort) {
279 SealHandleScope shs(isolate);
280 DCHECK(args.length() == 1);
281 CONVERT_SMI_ARG_CHECKED(message_id, 0);
282 const char* message =
283 GetBailoutReason(static_cast<BailoutReason>(message_id));
284 base::OS::PrintError("abort: %s\n", message);
285 isolate->PrintStack(stderr);
286 base::OS::Abort();
287 UNREACHABLE();
288 return NULL;
289}
290
291
292RUNTIME_FUNCTION(Runtime_AbortJS) {
293 HandleScope scope(isolate);
294 DCHECK(args.length() == 1);
295 CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
296 base::OS::PrintError("abort: %s\n", message->ToCString().get());
297 isolate->PrintStack(stderr);
298 base::OS::Abort();
299 UNREACHABLE();
300 return NULL;
301}
302
303
304RUNTIME_FUNCTION(Runtime_NativeScriptsCount) {
305 DCHECK(args.length() == 0);
306 return Smi::FromInt(Natives::GetBuiltinsCount());
307}
308
309
310// Returns V8 version as a string.
311RUNTIME_FUNCTION(Runtime_GetV8Version) {
312 HandleScope scope(isolate);
313 DCHECK(args.length() == 0);
314
315 const char* version_string = v8::V8::GetVersion();
316
317 return *isolate->factory()->NewStringFromAsciiChecked(version_string);
318}
319
320
321static int StackSize(Isolate* isolate) {
322 int n = 0;
323 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
324 return n;
325}
326
327
328static void PrintTransition(Isolate* isolate, Object* result) {
329 // indentation
330 {
331 const int nmax = 80;
332 int n = StackSize(isolate);
333 if (n <= nmax)
334 PrintF("%4d:%*s", n, n, "");
335 else
336 PrintF("%4d:%*s", n, nmax, "...");
337 }
338
339 if (result == NULL) {
340 JavaScriptFrame::PrintTop(isolate, stdout, true, false);
341 PrintF(" {\n");
342 } else {
343 // function result
344 PrintF("} -> ");
345 result->ShortPrint();
346 PrintF("\n");
347 }
348}
349
350
351RUNTIME_FUNCTION(Runtime_TraceEnter) {
352 SealHandleScope shs(isolate);
353 DCHECK(args.length() == 0);
354 PrintTransition(isolate, NULL);
355 return isolate->heap()->undefined_value();
356}
357
358
359RUNTIME_FUNCTION(Runtime_TraceExit) {
360 SealHandleScope shs(isolate);
361 DCHECK(args.length() == 1);
362 CONVERT_ARG_CHECKED(Object, obj, 0);
363 PrintTransition(isolate, obj);
364 return obj; // return TOS
365}
366
367
368RUNTIME_FUNCTION(Runtime_HaveSameMap) {
369 SealHandleScope shs(isolate);
370 DCHECK(args.length() == 2);
371 CONVERT_ARG_CHECKED(JSObject, obj1, 0);
372 CONVERT_ARG_CHECKED(JSObject, obj2, 1);
373 return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
374}
375
376
377#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
378 RUNTIME_FUNCTION(Runtime_Has##Name) { \
379 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
380 return isolate->heap()->ToBoolean(obj->Has##Name()); \
381 }
382
383ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
384ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
385ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
386ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
387ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
388ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
389ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
390ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
391// Properties test sitting with elements tests - not fooling anyone.
392ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
393
394#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
395
396
397#define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
398 RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \
399 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
400 return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
401 }
402
403TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
404
405#undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
406
407
408#define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
409 RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
410 CONVERT_ARG_CHECKED(JSObject, obj, 0); \
411 return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
412 }
413
414TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
415
416#undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
417}
418} // namespace v8::internal