LCOV - code coverage report
Current view: top level - src/runtime - runtime-classes.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 172 177 97.2 %
Date: 2017-10-20 Functions: 26 43 60.5 %

          Line data    Source code
       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/accessors.h"
      11             : #include "src/arguments.h"
      12             : #include "src/debug/debug.h"
      13             : #include "src/elements.h"
      14             : #include "src/isolate-inl.h"
      15             : #include "src/messages.h"
      16             : #include "src/runtime/runtime.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21             : 
      22          56 : RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
      23          28 :   HandleScope scope(isolate);
      24             :   DCHECK_EQ(0, args.length());
      25          56 :   THROW_NEW_ERROR_RETURN_FAILURE(
      26          28 :       isolate, NewReferenceError(MessageTemplate::kUnsupportedSuper));
      27             : }
      28             : 
      29             : 
      30         848 : RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
      31         424 :   HandleScope scope(isolate);
      32             :   DCHECK_EQ(1, args.length());
      33         848 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
      34         424 :   Handle<String> name(constructor->shared()->name(), isolate);
      35         848 :   THROW_NEW_ERROR_RETURN_FAILURE(
      36         424 :       isolate, NewTypeError(MessageTemplate::kConstructorNonCallable, name));
      37             : }
      38             : 
      39             : 
      40         144 : RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) {
      41          72 :   HandleScope scope(isolate);
      42             :   DCHECK_EQ(0, args.length());
      43         144 :   THROW_NEW_ERROR_RETURN_FAILURE(
      44          72 :       isolate, NewTypeError(MessageTemplate::kStaticPrototype));
      45             : }
      46             : 
      47         138 : RUNTIME_FUNCTION(Runtime_ThrowSuperAlreadyCalledError) {
      48          69 :   HandleScope scope(isolate);
      49             :   DCHECK_EQ(0, args.length());
      50         138 :   THROW_NEW_ERROR_RETURN_FAILURE(
      51          69 :       isolate, NewReferenceError(MessageTemplate::kSuperAlreadyCalled));
      52             : }
      53             : 
      54         354 : RUNTIME_FUNCTION(Runtime_ThrowSuperNotCalled) {
      55         177 :   HandleScope scope(isolate);
      56             :   DCHECK_EQ(0, args.length());
      57         354 :   THROW_NEW_ERROR_RETURN_FAILURE(
      58         177 :       isolate, NewReferenceError(MessageTemplate::kSuperNotCalled));
      59             : }
      60             : 
      61             : namespace {
      62             : 
      63         115 : Object* ThrowNotSuperConstructor(Isolate* isolate, Handle<Object> constructor,
      64             :                                  Handle<JSFunction> function) {
      65             :   Handle<String> super_name;
      66         115 :   if (constructor->IsJSFunction()) {
      67             :     super_name = handle(Handle<JSFunction>::cast(constructor)->shared()->name(),
      68             :                         isolate);
      69          49 :   } else if (constructor->IsOddball()) {
      70             :     DCHECK(constructor->IsNull(isolate));
      71             :     super_name = isolate->factory()->null_string();
      72             :   } else {
      73           0 :     super_name = Object::NoSideEffectsToString(isolate, constructor);
      74             :   }
      75             :   // null constructor
      76         115 :   if (super_name->length() == 0) {
      77             :     super_name = isolate->factory()->null_string();
      78             :   }
      79             :   Handle<String> function_name(function->shared()->name(), isolate);
      80             :   // anonymous class
      81         115 :   if (function_name->length() == 0) {
      82          72 :     THROW_NEW_ERROR_RETURN_FAILURE(
      83             :         isolate,
      84             :         NewTypeError(MessageTemplate::kNotSuperConstructorAnonymousClass,
      85             :                      super_name));
      86             :   }
      87         158 :   THROW_NEW_ERROR_RETURN_FAILURE(
      88             :       isolate, NewTypeError(MessageTemplate::kNotSuperConstructor, super_name,
      89             :                             function_name));
      90             : }
      91             : 
      92             : }  // namespace
      93             : 
      94         174 : RUNTIME_FUNCTION(Runtime_ThrowNotSuperConstructor) {
      95          87 :   HandleScope scope(isolate);
      96             :   DCHECK_EQ(2, args.length());
      97          87 :   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
      98         174 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
      99          87 :   return ThrowNotSuperConstructor(isolate, constructor, function);
     100             : }
     101             : 
     102         270 : RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
     103             :   DCHECK_EQ(0, args.length());
     104         135 :   return isolate->heap()->home_object_symbol();
     105             : }
     106             : 
     107       82979 : static MaybeHandle<Object> DefineClass(Isolate* isolate,
     108             :                                        Handle<Object> super_class,
     109             :                                        Handle<JSFunction> constructor,
     110             :                                        int start_position, int end_position) {
     111             :   Handle<Object> prototype_parent;
     112             :   Handle<Object> constructor_parent;
     113             : 
     114       82979 :   if (super_class->IsTheHole(isolate)) {
     115       73858 :     prototype_parent = isolate->initial_object_prototype();
     116             :   } else {
     117        9121 :     if (super_class->IsNull(isolate)) {
     118             :       prototype_parent = isolate->factory()->null_value();
     119        8860 :     } else if (super_class->IsConstructor()) {
     120             :       DCHECK(!super_class->IsJSFunction() ||
     121             :              !IsResumableFunction(
     122             :                  Handle<JSFunction>::cast(super_class)->shared()->kind()));
     123       17324 :       ASSIGN_RETURN_ON_EXCEPTION(
     124             :           isolate, prototype_parent,
     125             :           Runtime::GetObjectProperty(isolate, super_class,
     126             :                                      isolate->factory()->prototype_string()),
     127             :           Object);
     128       17306 :       if (!prototype_parent->IsNull(isolate) &&
     129             :           !prototype_parent->IsJSReceiver()) {
     130          90 :         THROW_NEW_ERROR(
     131             :             isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
     132             :                                   prototype_parent),
     133             :             Object);
     134             :       }
     135             :       constructor_parent = super_class;
     136             :     } else {
     137         396 :       THROW_NEW_ERROR(isolate,
     138             :                       NewTypeError(MessageTemplate::kExtendsValueNotConstructor,
     139             :                                    super_class),
     140             :                       Object);
     141             :     }
     142             :   }
     143             : 
     144             :   Handle<Map> map =
     145       82736 :       isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     146             :   map->set_is_prototype_map(true);
     147       82736 :   Map::SetPrototype(map, prototype_parent);
     148             :   map->SetConstructor(*constructor);
     149       82736 :   Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);
     150             : 
     151       82736 :   JSFunction::SetPrototype(constructor, prototype);
     152             :   PropertyAttributes attribs =
     153             :       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
     154      165472 :   RETURN_ON_EXCEPTION(isolate,
     155             :                       JSObject::SetOwnPropertyIgnoreAttributes(
     156             :                           constructor, isolate->factory()->prototype_string(),
     157             :                           prototype, attribs),
     158             :                       Object);
     159             : 
     160       82736 :   if (!constructor_parent.is_null()) {
     161        8617 :     MAYBE_RETURN_NULL(JSObject::SetPrototype(constructor, constructor_parent,
     162             :                                              false, Object::THROW_ON_ERROR));
     163             :   }
     164             : 
     165             :   JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
     166       82736 :                         constructor, DONT_ENUM);
     167             : 
     168             :   // Install private properties that are used to construct the FunctionToString.
     169      165472 :   RETURN_ON_EXCEPTION(
     170             :       isolate,
     171             :       Object::SetProperty(
     172             :           constructor, isolate->factory()->class_start_position_symbol(),
     173             :           handle(Smi::FromInt(start_position), isolate), LanguageMode::kStrict),
     174             :       Object);
     175      165472 :   RETURN_ON_EXCEPTION(
     176             :       isolate,
     177             :       Object::SetProperty(
     178             :           constructor, isolate->factory()->class_end_position_symbol(),
     179             :           handle(Smi::FromInt(end_position), isolate), LanguageMode::kStrict),
     180             :       Object);
     181             : 
     182             :   // Caller already has access to constructor, so return the prototype.
     183       82736 :   return prototype;
     184             : }
     185             : 
     186             : 
     187      165958 : RUNTIME_FUNCTION(Runtime_DefineClass) {
     188       82979 :   HandleScope scope(isolate);
     189             :   DCHECK_EQ(4, args.length());
     190       82979 :   CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 0);
     191      165958 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 1);
     192      165958 :   CONVERT_SMI_ARG_CHECKED(start_position, 2);
     193      165958 :   CONVERT_SMI_ARG_CHECKED(end_position, 3);
     194             : 
     195      165958 :   RETURN_RESULT_OR_FAILURE(
     196             :       isolate, DefineClass(isolate, super_class, constructor, start_position,
     197       82979 :                            end_position));
     198             : }
     199             : 
     200             : namespace {
     201       70014 : void InstallClassNameAccessor(Isolate* isolate, Handle<JSObject> object) {
     202             :   PropertyAttributes attrs =
     203             :       static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
     204             :   // Cannot fail since this should only be called when creating an object
     205             :   // literal.
     206      140028 :   CHECK(!JSObject::SetAccessor(
     207             :              object, Accessors::FunctionNameInfo(object->GetIsolate(), attrs))
     208             :              .is_null());
     209       70014 : }
     210             : }  // anonymous namespace
     211             : 
     212      137292 : RUNTIME_FUNCTION(Runtime_InstallClassNameAccessor) {
     213       68646 :   HandleScope scope(isolate);
     214             :   DCHECK_EQ(1, args.length());
     215      137292 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
     216       68646 :   InstallClassNameAccessor(isolate, object);
     217       68646 :   return *object;
     218             : }
     219             : 
     220        2772 : RUNTIME_FUNCTION(Runtime_InstallClassNameAccessorWithCheck) {
     221        1386 :   HandleScope scope(isolate);
     222             :   DCHECK_EQ(1, args.length());
     223        2772 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
     224             : 
     225             :   // If a property named "name" is already defined, exit.
     226        1386 :   Handle<Name> key = isolate->factory()->name_string();
     227        2772 :   if (JSObject::HasRealNamedProperty(object, key).FromMaybe(false)) {
     228             :     return *object;
     229             :   }
     230             : 
     231             :   // Define the "name" accessor.
     232        1368 :   InstallClassNameAccessor(isolate, object);
     233        1386 :   return *object;
     234             : }
     235             : 
     236             : namespace {
     237             : 
     238             : enum class SuperMode { kLoad, kStore };
     239             : 
     240        4065 : MaybeHandle<JSReceiver> GetSuperHolder(
     241           0 :     Isolate* isolate, Handle<Object> receiver, Handle<JSObject> home_object,
     242             :     SuperMode mode, MaybeHandle<Name> maybe_name, uint32_t index) {
     243        4065 :   if (home_object->IsAccessCheckNeeded() &&
     244           0 :       !isolate->MayAccess(handle(isolate->context()), home_object)) {
     245           0 :     isolate->ReportFailedAccessCheck(home_object);
     246           0 :     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, JSReceiver);
     247             :   }
     248             : 
     249        4065 :   PrototypeIterator iter(isolate, home_object);
     250             :   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
     251        4065 :   if (!proto->IsJSReceiver()) {
     252             :     MessageTemplate::Template message =
     253             :         mode == SuperMode::kLoad ? MessageTemplate::kNonObjectPropertyLoad
     254          72 :                                  : MessageTemplate::kNonObjectPropertyStore;
     255             :     Handle<Name> name;
     256          72 :     if (!maybe_name.ToHandle(&name)) {
     257          36 :       name = isolate->factory()->Uint32ToString(index);
     258             :     }
     259         144 :     THROW_NEW_ERROR(isolate, NewTypeError(message, name, proto), JSReceiver);
     260             :   }
     261        3993 :   return Handle<JSReceiver>::cast(proto);
     262             : }
     263             : 
     264        2136 : MaybeHandle<Object> LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
     265             :                                   Handle<JSObject> home_object,
     266             :                                   Handle<Name> name) {
     267             :   Handle<JSReceiver> holder;
     268        4272 :   ASSIGN_RETURN_ON_EXCEPTION(
     269             :       isolate, holder,
     270             :       GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad, name, 0),
     271             :       Object);
     272        2118 :   LookupIterator it(receiver, name, holder);
     273             :   Handle<Object> result;
     274        4236 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
     275        2118 :   return result;
     276             : }
     277             : 
     278         486 : MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
     279             :                                          Handle<Object> receiver,
     280             :                                          Handle<JSObject> home_object,
     281             :                                          uint32_t index) {
     282             :   Handle<JSReceiver> holder;
     283         972 :   ASSIGN_RETURN_ON_EXCEPTION(
     284             :       isolate, holder,
     285             :       GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad,
     286             :                      MaybeHandle<Name>(), index),
     287             :       Object);
     288             :   LookupIterator it(isolate, receiver, index, holder);
     289             :   Handle<Object> result;
     290         936 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
     291         468 :   return result;
     292             : }
     293             : 
     294             : }  // anonymous namespace
     295             : 
     296        3210 : RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
     297        1605 :   HandleScope scope(isolate);
     298             :   DCHECK_EQ(3, args.length());
     299        1605 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     300        3210 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     301        3210 :   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
     302             : 
     303        3210 :   RETURN_RESULT_OR_FAILURE(isolate,
     304        1605 :                            LoadFromSuper(isolate, receiver, home_object, name));
     305             : }
     306             : 
     307             : 
     308        2070 : RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
     309        1035 :   HandleScope scope(isolate);
     310             :   DCHECK_EQ(3, args.length());
     311        1035 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     312        2070 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     313        1035 :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
     314             : 
     315        1035 :   uint32_t index = 0;
     316             : 
     317        1035 :   if (key->ToArrayIndex(&index)) {
     318         918 :     RETURN_RESULT_OR_FAILURE(
     319             :         isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
     320             :   }
     321             : 
     322             :   Handle<Name> name;
     323        1152 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
     324             :                                      Object::ToName(isolate, key));
     325             :   // TODO(verwaest): Unify using LookupIterator.
     326         558 :   if (name->AsArrayIndex(&index)) {
     327          54 :     RETURN_RESULT_OR_FAILURE(
     328             :         isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
     329             :   }
     330        1062 :   RETURN_RESULT_OR_FAILURE(isolate,
     331        1035 :                            LoadFromSuper(isolate, receiver, home_object, name));
     332             : }
     333             : 
     334             : namespace {
     335             : 
     336        1002 : MaybeHandle<Object> StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
     337             :                                  Handle<Object> receiver, Handle<Name> name,
     338             :                                  Handle<Object> value,
     339             :                                  LanguageMode language_mode) {
     340             :   Handle<JSReceiver> holder;
     341        2004 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, holder,
     342             :                              GetSuperHolder(isolate, receiver, home_object,
     343             :                                             SuperMode::kStore, name, 0),
     344             :                              Object);
     345         984 :   LookupIterator it(receiver, name, holder);
     346         984 :   MAYBE_RETURN(Object::SetSuperProperty(&it, value, language_mode,
     347             :                                         Object::CERTAINLY_NOT_STORE_FROM_KEYED),
     348             :                MaybeHandle<Object>());
     349         799 :   return value;
     350             : }
     351             : 
     352         441 : MaybeHandle<Object> StoreElementToSuper(Isolate* isolate,
     353             :                                         Handle<JSObject> home_object,
     354             :                                         Handle<Object> receiver, uint32_t index,
     355             :                                         Handle<Object> value,
     356             :                                         LanguageMode language_mode) {
     357             :   Handle<JSReceiver> holder;
     358         882 :   ASSIGN_RETURN_ON_EXCEPTION(
     359             :       isolate, holder,
     360             :       GetSuperHolder(isolate, receiver, home_object, SuperMode::kStore,
     361             :                      MaybeHandle<Name>(), index),
     362             :       Object);
     363             :   LookupIterator it(isolate, receiver, index, holder);
     364         423 :   MAYBE_RETURN(Object::SetSuperProperty(&it, value, language_mode,
     365             :                                         Object::MAY_BE_STORE_FROM_KEYED),
     366             :                MaybeHandle<Object>());
     367         333 :   return value;
     368             : }
     369             : 
     370             : }  // anonymous namespace
     371             : 
     372         508 : RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
     373         254 :   HandleScope scope(isolate);
     374             :   DCHECK_EQ(4, args.length());
     375         254 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     376         508 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     377         508 :   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
     378         254 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
     379             : 
     380         508 :   RETURN_RESULT_OR_FAILURE(
     381             :       isolate, StoreToSuper(isolate, home_object, receiver, name, value,
     382         254 :                             LanguageMode::kStrict));
     383             : }
     384             : 
     385             : 
     386         572 : RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
     387         286 :   HandleScope scope(isolate);
     388             :   DCHECK_EQ(4, args.length());
     389         286 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     390         572 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     391         572 :   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
     392         286 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
     393             : 
     394         572 :   RETURN_RESULT_OR_FAILURE(
     395             :       isolate, StoreToSuper(isolate, home_object, receiver, name, value,
     396         286 :                             LanguageMode::kSloppy));
     397             : }
     398             : 
     399         921 : static MaybeHandle<Object> StoreKeyedToSuper(
     400             :     Isolate* isolate, Handle<JSObject> home_object, Handle<Object> receiver,
     401             :     Handle<Object> key, Handle<Object> value, LanguageMode language_mode) {
     402         921 :   uint32_t index = 0;
     403             : 
     404         921 :   if (key->ToArrayIndex(&index)) {
     405             :     return StoreElementToSuper(isolate, home_object, receiver, index, value,
     406         423 :                                language_mode);
     407             :   }
     408             :   Handle<Name> name;
     409         996 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
     410             :                              Object);
     411             :   // TODO(verwaest): Unify using LookupIterator.
     412         480 :   if (name->AsArrayIndex(&index)) {
     413             :     return StoreElementToSuper(isolate, home_object, receiver, index, value,
     414          18 :                                language_mode);
     415             :   }
     416             :   return StoreToSuper(isolate, home_object, receiver, name, value,
     417         462 :                       language_mode);
     418             : }
     419             : 
     420             : 
     421         630 : RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Strict) {
     422         315 :   HandleScope scope(isolate);
     423             :   DCHECK_EQ(4, args.length());
     424         315 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     425         630 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     426         315 :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
     427         315 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
     428             : 
     429         630 :   RETURN_RESULT_OR_FAILURE(
     430             :       isolate, StoreKeyedToSuper(isolate, home_object, receiver, key, value,
     431         315 :                                  LanguageMode::kStrict));
     432             : }
     433             : 
     434             : 
     435        1212 : RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) {
     436         606 :   HandleScope scope(isolate);
     437             :   DCHECK_EQ(4, args.length());
     438         606 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     439        1212 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     440         606 :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
     441         606 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
     442             : 
     443        1212 :   RETURN_RESULT_OR_FAILURE(
     444             :       isolate, StoreKeyedToSuper(isolate, home_object, receiver, key, value,
     445         606 :                                  LanguageMode::kSloppy));
     446             : }
     447             : 
     448             : 
     449          68 : RUNTIME_FUNCTION(Runtime_GetSuperConstructor) {
     450             :   SealHandleScope shs(isolate);
     451             :   DCHECK_EQ(1, args.length());
     452          68 :   CONVERT_ARG_CHECKED(JSFunction, active_function, 0);
     453          34 :   Object* prototype = active_function->map()->prototype();
     454          34 :   if (!prototype->IsConstructor()) {
     455          28 :     HandleScope scope(isolate);
     456             :     return ThrowNotSuperConstructor(isolate, handle(prototype, isolate),
     457          28 :                                     handle(active_function, isolate));
     458             :   }
     459             :   return prototype;
     460             : }
     461             : 
     462             : }  // namespace internal
     463             : }  // namespace v8

Generated by: LCOV version 1.10