blob: 7c827f0bd97cdbc49397b1fe9449f95d4281fa06 [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 <stdlib.h>
6#include <limits>
7
8#include "src/v8.h"
9
10#include "src/isolate-inl.h"
11#include "src/runtime/runtime.h"
12#include "src/runtime/runtime-utils.h"
13
14
15namespace v8 {
16namespace internal {
17
18
19RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) {
20 HandleScope scope(isolate);
21 DCHECK(args.length() == 0);
22 THROW_NEW_ERROR_RETURN_FAILURE(
23 isolate, NewReferenceError("non_method", HandleVector<Object>(NULL, 0)));
24}
25
26
27static Object* ThrowUnsupportedSuper(Isolate* isolate) {
28 THROW_NEW_ERROR_RETURN_FAILURE(
29 isolate,
30 NewReferenceError("unsupported_super", HandleVector<Object>(NULL, 0)));
31}
32
33
34RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
35 HandleScope scope(isolate);
36 DCHECK(args.length() == 0);
37 return ThrowUnsupportedSuper(isolate);
38}
39
40
41RUNTIME_FUNCTION(Runtime_ToMethod) {
42 HandleScope scope(isolate);
43 DCHECK(args.length() == 2);
44 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
45 CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
46 Handle<JSFunction> clone = JSFunction::CloneClosure(fun);
47 Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
48 JSObject::SetOwnPropertyIgnoreAttributes(clone, home_object_symbol,
49 home_object, DONT_ENUM).Assert();
50 return *clone;
51}
52
53
54RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
55 DCHECK(args.length() == 0);
56 return isolate->heap()->home_object_symbol();
57}
58
59
60RUNTIME_FUNCTION(Runtime_DefineClass) {
61 HandleScope scope(isolate);
62 DCHECK(args.length() == 6);
63 CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
64 CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
65 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
66 CONVERT_ARG_HANDLE_CHECKED(Script, script, 3);
67 CONVERT_SMI_ARG_CHECKED(start_position, 4);
68 CONVERT_SMI_ARG_CHECKED(end_position, 5);
69
70 Handle<Object> prototype_parent;
71 Handle<Object> constructor_parent;
72
73 if (super_class->IsTheHole()) {
74 prototype_parent = isolate->initial_object_prototype();
75 } else {
76 if (super_class->IsNull()) {
77 prototype_parent = isolate->factory()->null_value();
78 } else if (super_class->IsSpecFunction()) {
79 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
80 isolate, prototype_parent,
81 Runtime::GetObjectProperty(isolate, super_class,
82 isolate->factory()->prototype_string()));
83 if (!prototype_parent->IsNull() && !prototype_parent->IsSpecObject()) {
84 Handle<Object> args[1] = {prototype_parent};
85 THROW_NEW_ERROR_RETURN_FAILURE(
86 isolate, NewTypeError("prototype_parent_not_an_object",
87 HandleVector(args, 1)));
88 }
89 constructor_parent = super_class;
90 } else {
91 // TODO(arv): Should be IsConstructor.
92 Handle<Object> args[1] = {super_class};
93 THROW_NEW_ERROR_RETURN_FAILURE(
94 isolate,
95 NewTypeError("extends_value_not_a_function", HandleVector(args, 1)));
96 }
97 }
98
99 Handle<Map> map =
100 isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
101 map->SetPrototype(prototype_parent);
102 map->set_constructor(*constructor);
103 Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);
104
105 Handle<String> name_string = name->IsString()
106 ? Handle<String>::cast(name)
107 : isolate->factory()->empty_string();
108 constructor->shared()->set_name(*name_string);
109
110 JSFunction::SetPrototype(constructor, prototype);
111 PropertyAttributes attribs =
112 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
113 RETURN_FAILURE_ON_EXCEPTION(
114 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
115 constructor, isolate->factory()->prototype_string(),
116 prototype, attribs));
117
118 // TODO(arv): Only do this conditionally.
119 Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
120 RETURN_FAILURE_ON_EXCEPTION(
121 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
122 constructor, home_object_symbol, prototype, DONT_ENUM));
123
124 if (!constructor_parent.is_null()) {
125 RETURN_FAILURE_ON_EXCEPTION(
126 isolate,
127 JSObject::SetPrototype(constructor, constructor_parent, false));
128 }
129
130 JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
131 constructor, DONT_ENUM);
132
133 // Install private properties that are used to construct the FunctionToString.
134 RETURN_FAILURE_ON_EXCEPTION(
135 isolate, Object::SetProperty(constructor,
136 isolate->factory()->class_script_symbol(),
137 script, STRICT));
138 RETURN_FAILURE_ON_EXCEPTION(
139 isolate,
140 Object::SetProperty(
141 constructor, isolate->factory()->class_start_position_symbol(),
142 handle(Smi::FromInt(start_position), isolate), STRICT));
143 RETURN_FAILURE_ON_EXCEPTION(
144 isolate, Object::SetProperty(
145 constructor, isolate->factory()->class_end_position_symbol(),
146 handle(Smi::FromInt(end_position), isolate), STRICT));
147
148 return *constructor;
149}
150
151
152RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
153 HandleScope scope(isolate);
154 DCHECK(args.length() == 3);
155 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
156 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
157 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
158
159 uint32_t index;
160 if (key->ToArrayIndex(&index)) {
161 RETURN_FAILURE_ON_EXCEPTION(
162 isolate, JSObject::SetOwnElement(object, index, function, STRICT));
163 }
164
165 Handle<Name> name;
166 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
167 Runtime::ToName(isolate, key));
168 if (name->AsArrayIndex(&index)) {
169 RETURN_FAILURE_ON_EXCEPTION(
170 isolate, JSObject::SetOwnElement(object, index, function, STRICT));
171 } else {
172 RETURN_FAILURE_ON_EXCEPTION(
173 isolate,
174 JSObject::SetOwnPropertyIgnoreAttributes(object, name, function, NONE));
175 }
176 return isolate->heap()->undefined_value();
177}
178
179
180RUNTIME_FUNCTION(Runtime_DefineClassGetter) {
181 HandleScope scope(isolate);
182 DCHECK(args.length() == 3);
183 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
184 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
185 CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
186
187 Handle<Name> name;
188 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
189 Runtime::ToName(isolate, key));
190 RETURN_FAILURE_ON_EXCEPTION(
191 isolate,
192 JSObject::DefineAccessor(object, name, getter,
193 isolate->factory()->null_value(), NONE));
194 return isolate->heap()->undefined_value();
195}
196
197
198RUNTIME_FUNCTION(Runtime_DefineClassSetter) {
199 HandleScope scope(isolate);
200 DCHECK(args.length() == 3);
201 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
202 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
203 CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
204
205 Handle<Name> name;
206 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
207 Runtime::ToName(isolate, key));
208 RETURN_FAILURE_ON_EXCEPTION(
209 isolate,
210 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
211 setter, NONE));
212 return isolate->heap()->undefined_value();
213}
214
215
216RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
217 HandleScope shs(isolate);
218 DCHECK(args.length() == 1);
219 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
220
221 Handle<Object> script;
222 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
223 isolate, script,
224 Object::GetProperty(fun, isolate->factory()->class_script_symbol()));
225 if (!script->IsScript()) {
226 return isolate->heap()->undefined_value();
227 }
228
229 Handle<Symbol> start_position_symbol(
230 isolate->heap()->class_start_position_symbol());
231 Handle<Object> start_position;
232 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
233 isolate, start_position, Object::GetProperty(fun, start_position_symbol));
234
235 Handle<Symbol> end_position_symbol(
236 isolate->heap()->class_end_position_symbol());
237 Handle<Object> end_position;
238 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
239 isolate, end_position, Object::GetProperty(fun, end_position_symbol));
240
241 if (!start_position->IsSmi() || !end_position->IsSmi() ||
242 !Handle<Script>::cast(script)->HasValidSource()) {
243 return isolate->ThrowIllegalOperation();
244 }
245
246 Handle<String> source(String::cast(Handle<Script>::cast(script)->source()));
247 return *isolate->factory()->NewSubString(
248 source, Handle<Smi>::cast(start_position)->value(),
249 Handle<Smi>::cast(end_position)->value());
250}
251
252
253static Object* LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
254 Handle<JSObject> home_object, Handle<Name> name) {
255 if (home_object->IsAccessCheckNeeded() &&
256 !isolate->MayNamedAccess(home_object, name, v8::ACCESS_GET)) {
257 isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_GET);
258 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
259 }
260
261 PrototypeIterator iter(isolate, home_object);
262 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
263 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
264
265 LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
266 Handle<Object> result;
267 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
268 return *result;
269}
270
271
272static Object* LoadElementFromSuper(Isolate* isolate, Handle<Object> receiver,
273 Handle<JSObject> home_object,
274 uint32_t index) {
275 if (home_object->IsAccessCheckNeeded() &&
276 !isolate->MayIndexedAccess(home_object, index, v8::ACCESS_GET)) {
277 isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_GET);
278 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
279 }
280
281 PrototypeIterator iter(isolate, home_object);
282 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
283 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
284
285 Handle<Object> result;
286 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
287 isolate, result,
288 Object::GetElementWithReceiver(isolate, proto, receiver, index));
289 return *result;
290}
291
292
293RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
294 HandleScope scope(isolate);
295 DCHECK(args.length() == 3);
296 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
297 CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
298 CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
299
300 return LoadFromSuper(isolate, receiver, home_object, name);
301}
302
303
304RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
305 HandleScope scope(isolate);
306 DCHECK(args.length() == 3);
307 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
308 CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
309 CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
310
311 uint32_t index;
312 if (key->ToArrayIndex(&index)) {
313 return LoadElementFromSuper(isolate, receiver, home_object, index);
314 }
315
316 Handle<Name> name;
317 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
318 Runtime::ToName(isolate, key));
319 if (name->AsArrayIndex(&index)) {
320 return LoadElementFromSuper(isolate, receiver, home_object, index);
321 }
322 return LoadFromSuper(isolate, receiver, home_object, name);
323}
324
325
326static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
327 Handle<Object> receiver, Handle<Name> name,
328 Handle<Object> value, StrictMode strict_mode) {
329 if (home_object->IsAccessCheckNeeded() &&
330 !isolate->MayNamedAccess(home_object, name, v8::ACCESS_SET)) {
331 isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_SET);
332 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
333 }
334
335 PrototypeIterator iter(isolate, home_object);
336 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
337 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
338
339 LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
340 Handle<Object> result;
341 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
342 isolate, result,
343 Object::SetProperty(&it, value, strict_mode,
344 Object::CERTAINLY_NOT_STORE_FROM_KEYED,
345 Object::SUPER_PROPERTY));
346 return *result;
347}
348
349
350static Object* StoreElementToSuper(Isolate* isolate,
351 Handle<JSObject> home_object,
352 Handle<Object> receiver, uint32_t index,
353 Handle<Object> value,
354 StrictMode strict_mode) {
355 if (home_object->IsAccessCheckNeeded() &&
356 !isolate->MayIndexedAccess(home_object, index, v8::ACCESS_SET)) {
357 isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_SET);
358 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
359 }
360
361 PrototypeIterator iter(isolate, home_object);
362 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
363 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
364
365 Handle<Object> result;
366 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
367 isolate, result,
368 Object::SetElementWithReceiver(isolate, proto, receiver, index, value,
369 strict_mode));
370 return *result;
371}
372
373
374RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
375 HandleScope scope(isolate);
376 DCHECK(args.length() == 4);
377 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
378 CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
379 CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
380 CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
381
382 return StoreToSuper(isolate, home_object, receiver, name, value, STRICT);
383}
384
385
386RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
387 HandleScope scope(isolate);
388 DCHECK(args.length() == 4);
389 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
390 CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
391 CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
392 CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
393
394 return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY);
395}
396
397
398static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
399 Handle<Object> receiver, Handle<Object> key,
400 Handle<Object> value, StrictMode strict_mode) {
401 uint32_t index;
402
403 if (key->ToArrayIndex(&index)) {
404 return StoreElementToSuper(isolate, home_object, receiver, index, value,
405 strict_mode);
406 }
407 Handle<Name> name;
408 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
409 Runtime::ToName(isolate, key));
410 if (name->AsArrayIndex(&index)) {
411 return StoreElementToSuper(isolate, home_object, receiver, index, value,
412 strict_mode);
413 }
414 return StoreToSuper(isolate, home_object, receiver, name, value, strict_mode);
415}
416
417
418RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Strict) {
419 HandleScope scope(isolate);
420 DCHECK(args.length() == 4);
421 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
422 CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
423 CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
424 CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
425
426 return StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT);
427}
428
429
430RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) {
431 HandleScope scope(isolate);
432 DCHECK(args.length() == 4);
433 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
434 CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
435 CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
436 CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
437
438 return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY);
439}
440
441
442RUNTIME_FUNCTION(Runtime_DefaultConstructorSuperCall) {
443 HandleScope scope(isolate);
444 DCHECK(args.length() == 0);
445
446 // Compute the frame holding the arguments.
447 JavaScriptFrameIterator it(isolate);
448 it.AdvanceToArgumentsFrame();
449 JavaScriptFrame* frame = it.frame();
450
451 Handle<JSFunction> function(frame->function(), isolate);
452 Handle<Object> receiver(frame->receiver(), isolate);
453
454 Handle<Object> proto_function;
455 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, proto_function,
456 Runtime::GetPrototype(isolate, function));
457
458 // Get the actual number of provided arguments.
459 const int argc = frame->ComputeParametersCount();
460
461 // Loose upper bound to allow fuzzing. We'll most likely run out of
462 // stack space before hitting this limit.
463 static int kMaxArgc = 1000000;
464 RUNTIME_ASSERT(argc >= 0 && argc <= kMaxArgc);
465
466 // If there are too many arguments, allocate argv via malloc.
467 const int argv_small_size = 10;
468 Handle<Object> argv_small_buffer[argv_small_size];
469 SmartArrayPointer<Handle<Object> > argv_large_buffer;
470 Handle<Object>* argv = argv_small_buffer;
471 if (argc > argv_small_size) {
472 argv = new Handle<Object>[argc];
473 if (argv == NULL) return isolate->StackOverflow();
474 argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
475 }
476
477 for (int i = 0; i < argc; ++i) {
478 argv[i] = handle(frame->GetParameter(i), isolate);
479 }
480
481 Handle<Object> result;
482 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
483 isolate, result,
484 Execution::Call(isolate, proto_function, receiver, argc, argv, false));
485 return *result;
486}
487}
488} // namespace v8::internal