• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdlib.h>
8 #include <limits>
9 
10 #include "src/arguments.h"
11 #include "src/debug/debug.h"
12 #include "src/frames-inl.h"
13 #include "src/isolate-inl.h"
14 #include "src/messages.h"
15 #include "src/runtime/runtime.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 
RUNTIME_FUNCTION(Runtime_ThrowNonMethodError)21 RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) {
22   HandleScope scope(isolate);
23   DCHECK(args.length() == 0);
24   THROW_NEW_ERROR_RETURN_FAILURE(
25       isolate, NewReferenceError(MessageTemplate::kNonMethod));
26 }
27 
28 
RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError)29 RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
30   HandleScope scope(isolate);
31   DCHECK(args.length() == 0);
32   THROW_NEW_ERROR_RETURN_FAILURE(
33       isolate, NewReferenceError(MessageTemplate::kUnsupportedSuper));
34 }
35 
36 
RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError)37 RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
38   HandleScope scope(isolate);
39   DCHECK(args.length() == 1);
40   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
41   Handle<Object> name(constructor->shared()->name(), isolate);
42   THROW_NEW_ERROR_RETURN_FAILURE(
43       isolate, NewTypeError(MessageTemplate::kConstructorNonCallable, name));
44 }
45 
46 
RUNTIME_FUNCTION(Runtime_ThrowArrayNotSubclassableError)47 RUNTIME_FUNCTION(Runtime_ThrowArrayNotSubclassableError) {
48   HandleScope scope(isolate);
49   DCHECK(args.length() == 0);
50   THROW_NEW_ERROR_RETURN_FAILURE(
51       isolate, NewTypeError(MessageTemplate::kArrayNotSubclassable));
52 }
53 
54 
ThrowStaticPrototypeError(Isolate * isolate)55 static Object* ThrowStaticPrototypeError(Isolate* isolate) {
56   THROW_NEW_ERROR_RETURN_FAILURE(
57       isolate, NewTypeError(MessageTemplate::kStaticPrototype));
58 }
59 
60 
RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError)61 RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) {
62   HandleScope scope(isolate);
63   DCHECK(args.length() == 0);
64   return ThrowStaticPrototypeError(isolate);
65 }
66 
67 
RUNTIME_FUNCTION(Runtime_ThrowIfStaticPrototype)68 RUNTIME_FUNCTION(Runtime_ThrowIfStaticPrototype) {
69   HandleScope scope(isolate);
70   DCHECK(args.length() == 1);
71   CONVERT_ARG_HANDLE_CHECKED(Name, name, 0);
72   if (Name::Equals(name, isolate->factory()->prototype_string())) {
73     return ThrowStaticPrototypeError(isolate);
74   }
75   return *name;
76 }
77 
78 
RUNTIME_FUNCTION(Runtime_HomeObjectSymbol)79 RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
80   DCHECK(args.length() == 0);
81   return isolate->heap()->home_object_symbol();
82 }
83 
DefineClass(Isolate * isolate,Handle<Object> super_class,Handle<JSFunction> constructor,int start_position,int end_position)84 static MaybeHandle<Object> DefineClass(Isolate* isolate,
85                                        Handle<Object> super_class,
86                                        Handle<JSFunction> constructor,
87                                        int start_position, int end_position) {
88   Handle<Object> prototype_parent;
89   Handle<Object> constructor_parent;
90 
91   if (super_class->IsTheHole(isolate)) {
92     prototype_parent = isolate->initial_object_prototype();
93   } else {
94     if (super_class->IsNull(isolate)) {
95       prototype_parent = isolate->factory()->null_value();
96     } else if (super_class->IsConstructor()) {
97       DCHECK(!super_class->IsJSFunction() ||
98              !Handle<JSFunction>::cast(super_class)->shared()->is_resumable());
99       ASSIGN_RETURN_ON_EXCEPTION(
100           isolate, prototype_parent,
101           Runtime::GetObjectProperty(isolate, super_class,
102                                      isolate->factory()->prototype_string()),
103           Object);
104       if (!prototype_parent->IsNull(isolate) &&
105           !prototype_parent->IsJSReceiver()) {
106         THROW_NEW_ERROR(
107             isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
108                                   prototype_parent),
109             Object);
110       }
111       constructor_parent = super_class;
112     } else {
113       THROW_NEW_ERROR(isolate,
114                       NewTypeError(MessageTemplate::kExtendsValueNotConstructor,
115                                    super_class),
116                       Object);
117     }
118   }
119 
120   Handle<Map> map =
121       isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
122   map->set_is_prototype_map(true);
123   Map::SetPrototype(map, prototype_parent);
124   map->SetConstructor(*constructor);
125   Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);
126 
127   if (!super_class->IsTheHole(isolate)) {
128     // Derived classes, just like builtins, don't create implicit receivers in
129     // [[construct]]. Instead they just set up new.target and call into the
130     // constructor. Hence we can reuse the builtins construct stub for derived
131     // classes.
132     Handle<Code> stub(isolate->builtins()->JSBuiltinsConstructStubForDerived());
133     constructor->shared()->set_construct_stub(*stub);
134   }
135 
136   JSFunction::SetPrototype(constructor, prototype);
137   PropertyAttributes attribs =
138       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
139   RETURN_ON_EXCEPTION(isolate,
140                       JSObject::SetOwnPropertyIgnoreAttributes(
141                           constructor, isolate->factory()->prototype_string(),
142                           prototype, attribs),
143                       Object);
144 
145   // TODO(arv): Only do this conditionally.
146   Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
147   RETURN_ON_EXCEPTION(
148       isolate, JSObject::SetOwnPropertyIgnoreAttributes(
149                    constructor, home_object_symbol, prototype, DONT_ENUM),
150       Object);
151 
152   if (!constructor_parent.is_null()) {
153     MAYBE_RETURN_NULL(JSObject::SetPrototype(constructor, constructor_parent,
154                                              false, Object::THROW_ON_ERROR));
155   }
156 
157   JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
158                         constructor, DONT_ENUM);
159 
160   // Install private properties that are used to construct the FunctionToString.
161   RETURN_ON_EXCEPTION(
162       isolate,
163       Object::SetProperty(
164           constructor, isolate->factory()->class_start_position_symbol(),
165           handle(Smi::FromInt(start_position), isolate), STRICT),
166       Object);
167   RETURN_ON_EXCEPTION(
168       isolate, Object::SetProperty(
169                    constructor, isolate->factory()->class_end_position_symbol(),
170                    handle(Smi::FromInt(end_position), isolate), STRICT),
171       Object);
172 
173   return constructor;
174 }
175 
176 
RUNTIME_FUNCTION(Runtime_DefineClass)177 RUNTIME_FUNCTION(Runtime_DefineClass) {
178   HandleScope scope(isolate);
179   DCHECK(args.length() == 4);
180   CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 0);
181   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 1);
182   CONVERT_SMI_ARG_CHECKED(start_position, 2);
183   CONVERT_SMI_ARG_CHECKED(end_position, 3);
184 
185   RETURN_RESULT_OR_FAILURE(
186       isolate, DefineClass(isolate, super_class, constructor, start_position,
187                            end_position));
188 }
189 
190 
LoadFromSuper(Isolate * isolate,Handle<Object> receiver,Handle<JSObject> home_object,Handle<Name> name)191 static MaybeHandle<Object> LoadFromSuper(Isolate* isolate,
192                                          Handle<Object> receiver,
193                                          Handle<JSObject> home_object,
194                                          Handle<Name> name) {
195   if (home_object->IsAccessCheckNeeded() &&
196       !isolate->MayAccess(handle(isolate->context()), home_object)) {
197     isolate->ReportFailedAccessCheck(home_object);
198     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
199   }
200 
201   PrototypeIterator iter(isolate, home_object);
202   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
203   if (!proto->IsJSReceiver()) {
204     return Object::ReadAbsentProperty(isolate, proto, name);
205   }
206 
207   LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
208   Handle<Object> result;
209   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
210   return result;
211 }
212 
LoadElementFromSuper(Isolate * isolate,Handle<Object> receiver,Handle<JSObject> home_object,uint32_t index)213 static MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
214                                                 Handle<Object> receiver,
215                                                 Handle<JSObject> home_object,
216                                                 uint32_t index) {
217   if (home_object->IsAccessCheckNeeded() &&
218       !isolate->MayAccess(handle(isolate->context()), home_object)) {
219     isolate->ReportFailedAccessCheck(home_object);
220     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
221   }
222 
223   PrototypeIterator iter(isolate, home_object);
224   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
225   if (!proto->IsJSReceiver()) {
226     Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
227     return Object::ReadAbsentProperty(isolate, proto, name);
228   }
229 
230   LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
231   Handle<Object> result;
232   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
233   return result;
234 }
235 
236 
RUNTIME_FUNCTION(Runtime_LoadFromSuper)237 RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
238   HandleScope scope(isolate);
239   DCHECK_EQ(3, args.length());
240   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
241   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
242   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
243 
244   RETURN_RESULT_OR_FAILURE(isolate,
245                            LoadFromSuper(isolate, receiver, home_object, name));
246 }
247 
248 
RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper)249 RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
250   HandleScope scope(isolate);
251   DCHECK_EQ(3, args.length());
252   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
253   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
254   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
255 
256   uint32_t index = 0;
257 
258   if (key->ToArrayIndex(&index)) {
259     RETURN_RESULT_OR_FAILURE(
260         isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
261   }
262 
263   Handle<Name> name;
264   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
265                                      Object::ToName(isolate, key));
266   // TODO(verwaest): Unify using LookupIterator.
267   if (name->AsArrayIndex(&index)) {
268     RETURN_RESULT_OR_FAILURE(
269         isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
270   }
271   RETURN_RESULT_OR_FAILURE(isolate,
272                            LoadFromSuper(isolate, receiver, home_object, name));
273 }
274 
275 
StoreToSuper(Isolate * isolate,Handle<JSObject> home_object,Handle<Object> receiver,Handle<Name> name,Handle<Object> value,LanguageMode language_mode)276 static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
277                             Handle<Object> receiver, Handle<Name> name,
278                             Handle<Object> value, LanguageMode language_mode) {
279   if (home_object->IsAccessCheckNeeded() &&
280       !isolate->MayAccess(handle(isolate->context()), home_object)) {
281     isolate->ReportFailedAccessCheck(home_object);
282     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
283   }
284 
285   PrototypeIterator iter(isolate, home_object);
286   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
287   if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
288 
289   LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
290   MAYBE_RETURN(Object::SetSuperProperty(&it, value, language_mode,
291                                         Object::CERTAINLY_NOT_STORE_FROM_KEYED),
292                isolate->heap()->exception());
293   return *value;
294 }
295 
296 
StoreElementToSuper(Isolate * isolate,Handle<JSObject> home_object,Handle<Object> receiver,uint32_t index,Handle<Object> value,LanguageMode language_mode)297 static Object* StoreElementToSuper(Isolate* isolate,
298                                    Handle<JSObject> home_object,
299                                    Handle<Object> receiver, uint32_t index,
300                                    Handle<Object> value,
301                                    LanguageMode language_mode) {
302   if (home_object->IsAccessCheckNeeded() &&
303       !isolate->MayAccess(handle(isolate->context()), home_object)) {
304     isolate->ReportFailedAccessCheck(home_object);
305     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
306   }
307 
308   PrototypeIterator iter(isolate, home_object);
309   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
310   if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
311 
312   LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
313   MAYBE_RETURN(Object::SetSuperProperty(&it, value, language_mode,
314                                         Object::MAY_BE_STORE_FROM_KEYED),
315                isolate->heap()->exception());
316   return *value;
317 }
318 
319 
RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict)320 RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
321   HandleScope scope(isolate);
322   DCHECK(args.length() == 4);
323   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
324   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
325   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
326   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
327 
328   return StoreToSuper(isolate, home_object, receiver, name, value, STRICT);
329 }
330 
331 
RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy)332 RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
333   HandleScope scope(isolate);
334   DCHECK(args.length() == 4);
335   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
336   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
337   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
338   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
339 
340   return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY);
341 }
342 
343 
StoreKeyedToSuper(Isolate * isolate,Handle<JSObject> home_object,Handle<Object> receiver,Handle<Object> key,Handle<Object> value,LanguageMode language_mode)344 static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
345                                  Handle<Object> receiver, Handle<Object> key,
346                                  Handle<Object> value,
347                                  LanguageMode language_mode) {
348   uint32_t index = 0;
349 
350   if (key->ToArrayIndex(&index)) {
351     return StoreElementToSuper(isolate, home_object, receiver, index, value,
352                                language_mode);
353   }
354   Handle<Name> name;
355   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
356                                      Object::ToName(isolate, key));
357   // TODO(verwaest): Unify using LookupIterator.
358   if (name->AsArrayIndex(&index)) {
359     return StoreElementToSuper(isolate, home_object, receiver, index, value,
360                                language_mode);
361   }
362   return StoreToSuper(isolate, home_object, receiver, name, value,
363                       language_mode);
364 }
365 
366 
RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Strict)367 RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Strict) {
368   HandleScope scope(isolate);
369   DCHECK(args.length() == 4);
370   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
371   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
372   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
373   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
374 
375   return StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT);
376 }
377 
378 
RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy)379 RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) {
380   HandleScope scope(isolate);
381   DCHECK(args.length() == 4);
382   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
383   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
384   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
385   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
386 
387   return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY);
388 }
389 
390 
RUNTIME_FUNCTION(Runtime_GetSuperConstructor)391 RUNTIME_FUNCTION(Runtime_GetSuperConstructor) {
392   SealHandleScope shs(isolate);
393   DCHECK_EQ(1, args.length());
394   CONVERT_ARG_CHECKED(JSFunction, active_function, 0);
395   return active_function->map()->prototype();
396 }
397 
398 }  // namespace internal
399 }  // namespace v8
400