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/runtime/runtime-utils.h" 6 7 #include "src/accessors.h" 8 #include "src/arguments.h" 9 #include "src/compiler.h" 10 #include "src/frames-inl.h" 11 #include "src/isolate-inl.h" 12 #include "src/messages.h" 13 #include "src/wasm/wasm-module.h" 14 15 namespace v8 { 16 namespace internal { 17 18 RUNTIME_FUNCTION(Runtime_FunctionGetName) { 19 HandleScope scope(isolate); 20 DCHECK(args.length() == 1); 21 22 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); 23 if (function->IsJSBoundFunction()) { 24 RETURN_RESULT_OR_FAILURE( 25 isolate, JSBoundFunction::GetName( 26 isolate, Handle<JSBoundFunction>::cast(function))); 27 } else { 28 return *JSFunction::GetName(isolate, Handle<JSFunction>::cast(function)); 29 } 30 } 31 32 33 RUNTIME_FUNCTION(Runtime_FunctionSetName) { 34 HandleScope scope(isolate); 35 DCHECK(args.length() == 2); 36 37 CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0); 38 CONVERT_ARG_HANDLE_CHECKED(String, name, 1); 39 40 name = String::Flatten(name); 41 f->shared()->set_name(*name); 42 return isolate->heap()->undefined_value(); 43 } 44 45 46 RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) { 47 SealHandleScope shs(isolate); 48 DCHECK(args.length() == 1); 49 50 CONVERT_ARG_CHECKED(JSFunction, f, 0); 51 CHECK(f->RemovePrototype()); 52 f->shared()->set_construct_stub( 53 *isolate->builtins()->ConstructedNonConstructable()); 54 55 return isolate->heap()->undefined_value(); 56 } 57 58 59 RUNTIME_FUNCTION(Runtime_FunctionGetScript) { 60 HandleScope scope(isolate); 61 DCHECK_EQ(1, args.length()); 62 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); 63 64 if (function->IsJSFunction()) { 65 Handle<Object> script( 66 Handle<JSFunction>::cast(function)->shared()->script(), isolate); 67 if (script->IsScript()) { 68 return *Script::GetWrapper(Handle<Script>::cast(script)); 69 } 70 } 71 return isolate->heap()->undefined_value(); 72 } 73 74 75 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) { 76 HandleScope scope(isolate); 77 DCHECK_EQ(1, args.length()); 78 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); 79 if (function->IsJSFunction()) { 80 return *Handle<JSFunction>::cast(function)->shared()->GetSourceCode(); 81 } 82 return isolate->heap()->undefined_value(); 83 } 84 85 86 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) { 87 SealHandleScope shs(isolate); 88 DCHECK(args.length() == 1); 89 90 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 91 int pos = fun->shared()->start_position(); 92 return Smi::FromInt(pos); 93 } 94 95 96 RUNTIME_FUNCTION(Runtime_FunctionGetPositionForOffset) { 97 SealHandleScope shs(isolate); 98 DCHECK(args.length() == 2); 99 100 CONVERT_ARG_CHECKED(AbstractCode, abstract_code, 0); 101 CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]); 102 return Smi::FromInt(abstract_code->SourcePosition(offset)); 103 } 104 105 RUNTIME_FUNCTION(Runtime_FunctionGetContextData) { 106 SealHandleScope shs(isolate); 107 DCHECK(args.length() == 1); 108 109 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 110 FixedArray* array = fun->native_context()->embedder_data(); 111 return array->get(v8::Context::kDebugIdIndex); 112 } 113 114 RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName) { 115 SealHandleScope shs(isolate); 116 DCHECK(args.length() == 2); 117 118 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 119 CONVERT_ARG_CHECKED(String, name, 1); 120 fun->shared()->set_instance_class_name(name); 121 return isolate->heap()->undefined_value(); 122 } 123 124 125 RUNTIME_FUNCTION(Runtime_FunctionSetLength) { 126 SealHandleScope shs(isolate); 127 DCHECK(args.length() == 2); 128 129 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 130 CONVERT_SMI_ARG_CHECKED(length, 1); 131 CHECK((length & 0xC0000000) == 0xC0000000 || (length & 0xC0000000) == 0x0); 132 fun->shared()->set_length(length); 133 return isolate->heap()->undefined_value(); 134 } 135 136 137 RUNTIME_FUNCTION(Runtime_FunctionSetPrototype) { 138 HandleScope scope(isolate); 139 DCHECK(args.length() == 2); 140 141 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); 142 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); 143 CHECK(fun->IsConstructor()); 144 RETURN_FAILURE_ON_EXCEPTION(isolate, 145 Accessors::FunctionSetPrototype(fun, value)); 146 return args[0]; // return TOS 147 } 148 149 150 RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) { 151 SealHandleScope shs(isolate); 152 DCHECK(args.length() == 1); 153 154 CONVERT_ARG_CHECKED(JSFunction, f, 0); 155 return isolate->heap()->ToBoolean(f->shared()->IsApiFunction()); 156 } 157 158 159 RUNTIME_FUNCTION(Runtime_SetCode) { 160 HandleScope scope(isolate); 161 DCHECK(args.length() == 2); 162 163 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0); 164 CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1); 165 166 Handle<SharedFunctionInfo> target_shared(target->shared()); 167 Handle<SharedFunctionInfo> source_shared(source->shared()); 168 169 if (!Compiler::Compile(source, Compiler::KEEP_EXCEPTION)) { 170 return isolate->heap()->exception(); 171 } 172 173 // Mark both, the source and the target, as un-flushable because the 174 // shared unoptimized code makes them impossible to enqueue in a list. 175 DCHECK(target_shared->code()->gc_metadata() == NULL); 176 DCHECK(source_shared->code()->gc_metadata() == NULL); 177 target_shared->set_dont_flush(true); 178 source_shared->set_dont_flush(true); 179 180 // Set the code, scope info, formal parameter count, and the length 181 // of the target shared function info. 182 target_shared->ReplaceCode(source_shared->code()); 183 if (source_shared->HasBytecodeArray()) { 184 target_shared->set_bytecode_array(source_shared->bytecode_array()); 185 } 186 target_shared->set_scope_info(source_shared->scope_info()); 187 target_shared->set_length(source_shared->length()); 188 target_shared->set_num_literals(source_shared->num_literals()); 189 target_shared->set_feedback_metadata(source_shared->feedback_metadata()); 190 target_shared->set_internal_formal_parameter_count( 191 source_shared->internal_formal_parameter_count()); 192 target_shared->set_start_position_and_type( 193 source_shared->start_position_and_type()); 194 target_shared->set_end_position(source_shared->end_position()); 195 bool was_native = target_shared->native(); 196 target_shared->set_compiler_hints(source_shared->compiler_hints()); 197 target_shared->set_opt_count_and_bailout_reason( 198 source_shared->opt_count_and_bailout_reason()); 199 target_shared->set_native(was_native); 200 target_shared->set_profiler_ticks(source_shared->profiler_ticks()); 201 SharedFunctionInfo::SetScript( 202 target_shared, Handle<Object>(source_shared->script(), isolate)); 203 204 // Set the code of the target function. 205 target->ReplaceCode(source_shared->code()); 206 DCHECK(target->next_function_link()->IsUndefined(isolate)); 207 208 Handle<Context> context(source->context()); 209 target->set_context(*context); 210 211 // Make sure we get a fresh copy of the literal vector to avoid cross 212 // context contamination, and that the literal vector makes it's way into 213 // the target_shared optimized code map. 214 JSFunction::EnsureLiterals(target); 215 216 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { 217 isolate->logger()->LogExistingFunction( 218 source_shared, Handle<AbstractCode>(source_shared->abstract_code())); 219 } 220 221 return *target; 222 } 223 224 225 // Set the native flag on the function. 226 // This is used to decide if we should transform null and undefined 227 // into the global object when doing call and apply. 228 RUNTIME_FUNCTION(Runtime_SetNativeFlag) { 229 SealHandleScope shs(isolate); 230 DCHECK_EQ(1, args.length()); 231 232 CONVERT_ARG_CHECKED(Object, object, 0); 233 234 if (object->IsJSFunction()) { 235 JSFunction* func = JSFunction::cast(object); 236 func->shared()->set_native(true); 237 } 238 return isolate->heap()->undefined_value(); 239 } 240 241 242 RUNTIME_FUNCTION(Runtime_IsConstructor) { 243 SealHandleScope shs(isolate); 244 DCHECK_EQ(1, args.length()); 245 CONVERT_ARG_CHECKED(Object, object, 0); 246 return isolate->heap()->ToBoolean(object->IsConstructor()); 247 } 248 249 RUNTIME_FUNCTION(Runtime_SetForceInlineFlag) { 250 SealHandleScope shs(isolate); 251 DCHECK_EQ(1, args.length()); 252 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 253 254 if (object->IsJSFunction()) { 255 JSFunction* func = JSFunction::cast(*object); 256 func->shared()->set_force_inline(true); 257 } 258 return isolate->heap()->undefined_value(); 259 } 260 261 262 RUNTIME_FUNCTION(Runtime_Call) { 263 HandleScope scope(isolate); 264 DCHECK_LE(2, args.length()); 265 int const argc = args.length() - 2; 266 CONVERT_ARG_HANDLE_CHECKED(Object, target, 0); 267 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); 268 ScopedVector<Handle<Object>> argv(argc); 269 for (int i = 0; i < argc; ++i) { 270 argv[i] = args.at<Object>(2 + i); 271 } 272 RETURN_RESULT_OR_FAILURE( 273 isolate, Execution::Call(isolate, target, receiver, argc, argv.start())); 274 } 275 276 277 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee. 278 RUNTIME_FUNCTION(Runtime_ConvertReceiver) { 279 HandleScope scope(isolate); 280 DCHECK(args.length() == 1); 281 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); 282 return *Object::ConvertReceiver(isolate, receiver).ToHandleChecked(); 283 } 284 285 286 RUNTIME_FUNCTION(Runtime_IsFunction) { 287 SealHandleScope shs(isolate); 288 DCHECK_EQ(1, args.length()); 289 CONVERT_ARG_CHECKED(Object, object, 0); 290 return isolate->heap()->ToBoolean(object->IsFunction()); 291 } 292 293 294 RUNTIME_FUNCTION(Runtime_FunctionToString) { 295 HandleScope scope(isolate); 296 DCHECK_EQ(1, args.length()); 297 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); 298 return function->IsJSBoundFunction() 299 ? *JSBoundFunction::ToString( 300 Handle<JSBoundFunction>::cast(function)) 301 : *JSFunction::ToString(Handle<JSFunction>::cast(function)); 302 } 303 304 } // namespace internal 305 } // namespace v8 306