OLD | NEW |
(Empty) | |
| 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. |
| 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/runtime/runtime.h" |
| 11 #include "src/runtime/runtime-utils.h" |
| 12 |
| 13 namespace v8 { |
| 14 namespace internal { |
| 15 |
| 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(); |
| 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 |
| 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(); |
| 38 #else |
| 39 return isolate->heap()->false_value(); |
| 40 #endif |
| 41 } |
| 42 |
| 43 |
| 44 RUNTIME_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 |
| 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())); |
| 62 |
| 63 // If the function is optimized, just return. |
| 64 if (function->IsOptimized()) return isolate->heap()->undefined_value(); |
| 65 |
| 66 function->MarkForOptimization(); |
| 67 |
| 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(); |
| 79 } |
| 80 } |
| 81 |
| 82 return isolate->heap()->undefined_value(); |
| 83 } |
| 84 |
| 85 |
| 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(); |
| 92 } |
| 93 |
| 94 |
| 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". |
| 100 } |
| 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; |
| 106 } |
| 107 } |
| 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(); |
| 113 base::OS::Sleep(50); |
| 114 } |
| 115 } |
| 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". |
| 121 } |
| 122 if (FLAG_deopt_every_n_times) { |
| 123 return Smi::FromInt(6); // 6 == "maybe deopted". |
| 124 } |
| 125 if (function->IsOptimized() && function->code()->is_turbofanned()) { |
| 126 return Smi::FromInt(7); // 7 == "TurboFan compiler". |
| 127 } |
| 128 return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes". |
| 129 : Smi::FromInt(2); // 2 == "no". |
| 130 } |
| 131 |
| 132 |
| 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(); |
| 139 } |
| 140 |
| 141 |
| 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()); |
| 147 } |
| 148 |
| 149 |
| 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(); |
| 158 } |
| 159 return isolate->heap()->undefined_value(); |
| 160 } |
| 161 |
| 162 |
| 163 RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) { |
| 164 HandleScope scope(isolate); |
| 165 DCHECK(args.length() == 0); |
| 166 isolate->heap()->NotifyContextDisposed(); |
| 167 return isolate->heap()->undefined_value(); |
| 168 } |
| 169 |
| 170 |
| 171 RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) { |
| 172 SealHandleScope shs(isolate); |
| 173 DCHECK(args.length() == 2 || args.length() == 3); |
| 174 #ifdef DEBUG |
| 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(); |
| 184 } else { |
| 185 isolate->heap()->DisableInlineAllocation(); |
| 186 } |
| 187 } |
| 188 #endif |
| 189 return isolate->heap()->undefined_value(); |
| 190 } |
| 191 |
| 192 |
| 193 RUNTIME_FUNCTION(Runtime_DebugPrint) { |
| 194 SealHandleScope shs(isolate); |
| 195 DCHECK(args.length() == 1); |
| 196 |
| 197 OFStream os(stdout); |
| 198 #ifdef DEBUG |
| 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() << ": "; |
| 206 } else { |
| 207 os << "DebugPrint: "; |
| 208 } |
| 209 args[0]->Print(os); |
| 210 if (args[0]->IsHeapObject()) { |
| 211 os << "\n"; |
| 212 HeapObject::cast(args[0])->map()->Print(os); |
| 213 } |
| 214 #else |
| 215 // ShortPrint is available in release mode. Print is not. |
| 216 os << Brief(args[0]); |
| 217 #endif |
| 218 os << endl; |
| 219 |
| 220 return args[0]; // return TOS |
| 221 } |
| 222 |
| 223 |
| 224 RUNTIME_FUNCTION(Runtime_DebugTrace) { |
| 225 SealHandleScope shs(isolate); |
| 226 DCHECK(args.length() == 0); |
| 227 isolate->PrintStack(stdout); |
| 228 return isolate->heap()->undefined_value(); |
| 229 } |
| 230 |
| 231 |
| 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); |
| 237 |
| 238 CONVERT_ARG_CHECKED(String, string, 0); |
| 239 ConsStringIteratorOp op; |
| 240 StringCharacterStream stream(string, &op); |
| 241 while (stream.HasMore()) { |
| 242 uint16_t character = stream.GetNext(); |
| 243 PrintF("%c", character); |
| 244 } |
| 245 return string; |
| 246 } |
| 247 |
| 248 |
| 249 RUNTIME_FUNCTION(Runtime_SystemBreak) { |
| 250 SealHandleScope shs(isolate); |
| 251 DCHECK(args.length() == 0); |
| 252 base::OS::DebugBreak(); |
| 253 return isolate->heap()->undefined_value(); |
| 254 } |
| 255 |
| 256 |
| 257 // Sets a v8 flag. |
| 258 RUNTIME_FUNCTION(Runtime_SetFlags) { |
| 259 SealHandleScope shs(isolate); |
| 260 DCHECK(args.length() == 1); |
| 261 CONVERT_ARG_CHECKED(String, arg, 0); |
| 262 SmartArrayPointer<char> flags = |
| 263 arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
| 264 FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get())); |
| 265 return isolate->heap()->undefined_value(); |
| 266 } |
| 267 |
| 268 |
| 269 RUNTIME_FUNCTION(Runtime_Abort) { |
| 270 SealHandleScope shs(isolate); |
| 271 DCHECK(args.length() == 1); |
| 272 CONVERT_SMI_ARG_CHECKED(message_id, 0); |
| 273 const char* message = |
| 274 GetBailoutReason(static_cast<BailoutReason>(message_id)); |
| 275 base::OS::PrintError("abort: %s\n", message); |
| 276 isolate->PrintStack(stderr); |
| 277 base::OS::Abort(); |
| 278 UNREACHABLE(); |
| 279 return NULL; |
| 280 } |
| 281 |
| 282 |
| 283 RUNTIME_FUNCTION(Runtime_AbortJS) { |
| 284 HandleScope scope(isolate); |
| 285 DCHECK(args.length() == 1); |
| 286 CONVERT_ARG_HANDLE_CHECKED(String, message, 0); |
| 287 base::OS::PrintError("abort: %s\n", message->ToCString().get()); |
| 288 isolate->PrintStack(stderr); |
| 289 base::OS::Abort(); |
| 290 UNREACHABLE(); |
| 291 return NULL; |
| 292 } |
| 293 |
| 294 |
| 295 RUNTIME_FUNCTION(Runtime_HaveSameMap) { |
| 296 SealHandleScope shs(isolate); |
| 297 DCHECK(args.length() == 2); |
| 298 CONVERT_ARG_CHECKED(JSObject, obj1, 0); |
| 299 CONVERT_ARG_CHECKED(JSObject, obj2, 1); |
| 300 return isolate->heap()->ToBoolean(obj1->map() == obj2->map()); |
| 301 } |
| 302 |
| 303 |
| 304 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \ |
| 305 RUNTIME_FUNCTION(Runtime_Has##Name) { \ |
| 306 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ |
| 307 return isolate->heap()->ToBoolean(obj->Has##Name()); \ |
| 308 } |
| 309 |
| 310 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements) |
| 311 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements) |
| 312 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements) |
| 313 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements) |
| 314 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements) |
| 315 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements) |
| 316 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements) |
| 317 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements) |
| 318 // Properties test sitting with elements tests - not fooling anyone. |
| 319 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties) |
| 320 |
| 321 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION |
| 322 } |
| 323 } // namespace v8::internal |
OLD | NEW |