LCOV - code coverage report
Current view: top level - src - accessors.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 295 314 93.9 %
Date: 2019-01-20 Functions: 48 48 100.0 %

          Line data    Source code
       1             : // Copyright 2012 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/accessors.h"
       6             : 
       7             : #include "src/api-inl.h"
       8             : #include "src/contexts.h"
       9             : #include "src/counters.h"
      10             : #include "src/deoptimizer.h"
      11             : #include "src/execution.h"
      12             : #include "src/frames-inl.h"
      13             : #include "src/heap/factory.h"
      14             : #include "src/isolate-inl.h"
      15             : #include "src/messages.h"
      16             : #include "src/objects/api-callbacks.h"
      17             : #include "src/objects/js-array-inl.h"
      18             : #include "src/objects/module-inl.h"
      19             : #include "src/property-details.h"
      20             : #include "src/prototype.h"
      21             : 
      22             : namespace v8 {
      23             : namespace internal {
      24             : 
      25       31952 : Handle<AccessorInfo> Accessors::MakeAccessor(
      26             :     Isolate* isolate, Handle<Name> name, AccessorNameGetterCallback getter,
      27             :     AccessorNameBooleanSetterCallback setter) {
      28             :   Factory* factory = isolate->factory();
      29       31952 :   Handle<AccessorInfo> info = factory->NewAccessorInfo();
      30       31952 :   info->set_all_can_read(false);
      31       31952 :   info->set_all_can_write(false);
      32       31952 :   info->set_is_special_data_property(true);
      33       31952 :   info->set_is_sloppy(false);
      34       31952 :   info->set_replace_on_access(false);
      35       31952 :   info->set_getter_side_effect_type(SideEffectType::kHasSideEffect);
      36       31952 :   info->set_setter_side_effect_type(SideEffectType::kHasSideEffect);
      37       31952 :   name = factory->InternalizeName(name);
      38       31952 :   info->set_name(*name);
      39       31952 :   Handle<Object> get = v8::FromCData(isolate, getter);
      40       31952 :   if (setter == nullptr) setter = &ReconfigureToDataProperty;
      41       31952 :   Handle<Object> set = v8::FromCData(isolate, setter);
      42       31952 :   info->set_getter(*get);
      43       31952 :   info->set_setter(*set);
      44       31952 :   Address redirected = info->redirected_getter();
      45       31952 :   if (redirected != kNullAddress) {
      46       30972 :     Handle<Object> js_get = v8::FromCData(isolate, redirected);
      47       30972 :     info->set_js_getter(*js_get);
      48             :   }
      49       31952 :   return info;
      50             : }
      51             : 
      52             : static V8_INLINE bool CheckForName(Isolate* isolate, Handle<Name> name,
      53             :                                    Handle<String> property_name, int offset,
      54             :                                    FieldIndex::Encoding encoding,
      55             :                                    FieldIndex* index) {
      56       83144 :   if (Name::Equals(isolate, name, property_name)) {
      57       68490 :     *index = FieldIndex::ForInObjectOffset(offset, encoding);
      58             :     return true;
      59             :   }
      60             :   return false;
      61             : }
      62             : 
      63             : 
      64             : // Returns true for properties that are accessors to object fields.
      65             : // If true, *object_offset contains offset of object field.
      66      264407 : bool Accessors::IsJSObjectFieldAccessor(Isolate* isolate, Handle<Map> map,
      67             :                                         Handle<Name> name, FieldIndex* index) {
      68      264408 :   switch (map->instance_type()) {
      69             :     case JS_ARRAY_TYPE:
      70             :       return CheckForName(isolate, name, isolate->factory()->length_string(),
      71       83011 :                           JSArray::kLengthOffset, FieldIndex::kTagged, index);
      72             :     default:
      73      181399 :       if (map->instance_type() < FIRST_NONSTRING_TYPE) {
      74             :         return CheckForName(isolate, name, isolate->factory()->length_string(),
      75         135 :                             String::kLengthOffset, FieldIndex::kWord32, index);
      76             :       }
      77             : 
      78             :       return false;
      79             :   }
      80             : }
      81             : 
      82             : V8_WARN_UNUSED_RESULT MaybeHandle<Object>
      83       15348 : Accessors::ReplaceAccessorWithDataProperty(Handle<Object> receiver,
      84             :                                            Handle<JSObject> holder,
      85             :                                            Handle<Name> name,
      86             :                                            Handle<Object> value) {
      87             :   LookupIterator it(receiver, name, holder,
      88       15348 :                     LookupIterator::OWN_SKIP_INTERCEPTOR);
      89             :   // Skip any access checks we might hit. This accessor should never hit in a
      90             :   // situation where the caller does not have access.
      91       15348 :   if (it.state() == LookupIterator::ACCESS_CHECK) {
      92           0 :     CHECK(it.HasAccess());
      93           0 :     it.Next();
      94             :   }
      95             :   DCHECK(holder.is_identical_to(it.GetHolder<JSObject>()));
      96       15348 :   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
      97       15348 :   it.ReconfigureDataProperty(value, it.property_attributes());
      98       15348 :   return value;
      99             : }
     100             : 
     101             : 
     102             : //
     103             : // Accessors::ReconfigureToDataProperty
     104             : //
     105        1552 : void Accessors::ReconfigureToDataProperty(
     106             :     v8::Local<v8::Name> key, v8::Local<v8::Value> val,
     107             :     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     108             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     109             :   RuntimeCallTimerScope stats_scope(
     110        1552 :       isolate, RuntimeCallCounterId::kReconfigureToDataProperty);
     111             :   HandleScope scope(isolate);
     112             :   Handle<Object> receiver = Utils::OpenHandle(*info.This());
     113             :   Handle<JSObject> holder =
     114        1552 :       Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
     115        1552 :   Handle<Name> name = Utils::OpenHandle(*key);
     116        1552 :   Handle<Object> value = Utils::OpenHandle(*val);
     117             :   MaybeHandle<Object> result =
     118        1552 :       Accessors::ReplaceAccessorWithDataProperty(receiver, holder, name, value);
     119        1552 :   if (result.is_null()) {
     120           0 :     isolate->OptionalRescheduleException(false);
     121             :   } else {
     122             :     info.GetReturnValue().Set(true);
     123             :   }
     124        1552 : }
     125             : 
     126             : 
     127             : //
     128             : // Accessors::ArgumentsIterator
     129             : //
     130             : 
     131             : 
     132        6511 : void Accessors::ArgumentsIteratorGetter(
     133             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     134             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     135             :   DisallowHeapAllocation no_allocation;
     136             :   HandleScope scope(isolate);
     137       13022 :   Object result = isolate->native_context()->array_values_iterator();
     138             :   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
     139        6511 : }
     140             : 
     141          56 : Handle<AccessorInfo> Accessors::MakeArgumentsIteratorInfo(Isolate* isolate) {
     142             :   Handle<Name> name = isolate->factory()->iterator_symbol();
     143          56 :   return MakeAccessor(isolate, name, &ArgumentsIteratorGetter, nullptr);
     144             : }
     145             : 
     146             : 
     147             : //
     148             : // Accessors::ArrayLength
     149             : //
     150             : 
     151             : 
     152      140914 : void Accessors::ArrayLengthGetter(
     153             :     v8::Local<v8::Name> name,
     154             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     155             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     156             :   RuntimeCallTimerScope timer(isolate,
     157      140914 :                               RuntimeCallCounterId::kArrayLengthGetter);
     158             :   DisallowHeapAllocation no_allocation;
     159             :   HandleScope scope(isolate);
     160      140914 :   JSArray holder = JSArray::cast(*Utils::OpenHandle(*info.Holder()));
     161      140914 :   Object result = holder->length();
     162             :   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
     163      140914 : }
     164             : 
     165      485048 : void Accessors::ArrayLengthSetter(
     166             :     v8::Local<v8::Name> name, v8::Local<v8::Value> val,
     167             :     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     168             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     169             :   RuntimeCallTimerScope timer(isolate,
     170      485048 :                               RuntimeCallCounterId::kArrayLengthSetter);
     171             :   HandleScope scope(isolate);
     172             : 
     173             :   DCHECK(Utils::OpenHandle(*name)->SameValue(
     174             :       ReadOnlyRoots(isolate).length_string()));
     175             : 
     176             :   Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder());
     177      485048 :   Handle<JSArray> array = Handle<JSArray>::cast(object);
     178      485048 :   Handle<Object> length_obj = Utils::OpenHandle(*val);
     179             : 
     180      485048 :   bool was_readonly = JSArray::HasReadOnlyLength(array);
     181             : 
     182      485048 :   uint32_t length = 0;
     183      485048 :   if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
     184         153 :     isolate->OptionalRescheduleException(false);
     185         153 :     return;
     186             :   }
     187             : 
     188     1454685 :   if (!was_readonly && V8_UNLIKELY(JSArray::HasReadOnlyLength(array)) &&
     189      484949 :       length != array->length()->Number()) {
     190             :     // AnythingToArrayLength() may have called setter re-entrantly and modified
     191             :     // its property descriptor. Don't perform this check if "length" was
     192             :     // previously readonly, as this may have been called during
     193             :     // DefineOwnPropertyIgnoreAttributes().
     194          18 :     if (info.ShouldThrowOnError()) {
     195             :       Factory* factory = isolate->factory();
     196             :       isolate->Throw(*factory->NewTypeError(
     197             :           MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name),
     198          27 :           i::Object::TypeOf(isolate, object), object));
     199           9 :       isolate->OptionalRescheduleException(false);
     200             :     } else {
     201             :       info.GetReturnValue().Set(false);
     202             :     }
     203             :     return;
     204             :   }
     205             : 
     206      484877 :   JSArray::SetLength(array, length);
     207             : 
     208      484877 :   uint32_t actual_new_len = 0;
     209      969754 :   CHECK(array->length()->ToArrayLength(&actual_new_len));
     210             :   // Fail if there were non-deletable elements.
     211      484877 :   if (actual_new_len != length) {
     212          63 :     if (info.ShouldThrowOnError()) {
     213             :       Factory* factory = isolate->factory();
     214             :       isolate->Throw(*factory->NewTypeError(
     215             :           MessageTemplate::kStrictDeleteProperty,
     216          54 :           factory->NewNumberFromUint(actual_new_len - 1), array));
     217          27 :       isolate->OptionalRescheduleException(false);
     218             :     } else {
     219             :       info.GetReturnValue().Set(false);
     220             :     }
     221             :   } else {
     222             :     info.GetReturnValue().Set(true);
     223             :   }
     224             : }
     225             : 
     226          56 : Handle<AccessorInfo> Accessors::MakeArrayLengthInfo(Isolate* isolate) {
     227             :   return MakeAccessor(isolate, isolate->factory()->length_string(),
     228          56 :                       &ArrayLengthGetter, &ArrayLengthSetter);
     229             : }
     230             : 
     231             : //
     232             : // Accessors::ModuleNamespaceEntry
     233             : //
     234             : 
     235       31235 : void Accessors::ModuleNamespaceEntryGetter(
     236             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     237             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     238             :   HandleScope scope(isolate);
     239             :   JSModuleNamespace holder =
     240       31235 :       JSModuleNamespace::cast(*Utils::OpenHandle(*info.Holder()));
     241             :   Handle<Object> result;
     242       31235 :   if (!holder
     243       31235 :            ->GetExport(isolate, Handle<String>::cast(Utils::OpenHandle(*name)))
     244       62470 :            .ToHandle(&result)) {
     245          68 :     isolate->OptionalRescheduleException(false);
     246             :   } else {
     247             :     info.GetReturnValue().Set(Utils::ToLocal(result));
     248             :   }
     249       31235 : }
     250             : 
     251          45 : void Accessors::ModuleNamespaceEntrySetter(
     252             :     v8::Local<v8::Name> name, v8::Local<v8::Value> val,
     253             :     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     254             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     255             :   HandleScope scope(isolate);
     256             :   Factory* factory = isolate->factory();
     257             :   Handle<JSModuleNamespace> holder =
     258          45 :       Handle<JSModuleNamespace>::cast(Utils::OpenHandle(*info.Holder()));
     259             : 
     260          45 :   if (info.ShouldThrowOnError()) {
     261             :     isolate->Throw(*factory->NewTypeError(
     262             :         MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name),
     263          81 :         i::Object::TypeOf(isolate, holder), holder));
     264          27 :     isolate->OptionalRescheduleException(false);
     265             :   } else {
     266             :     info.GetReturnValue().Set(false);
     267             :   }
     268          45 : }
     269             : 
     270       30351 : Handle<AccessorInfo> Accessors::MakeModuleNamespaceEntryInfo(
     271             :     Isolate* isolate, Handle<String> name) {
     272             :   return MakeAccessor(isolate, name, &ModuleNamespaceEntryGetter,
     273       30351 :                       &ModuleNamespaceEntrySetter);
     274             : }
     275             : 
     276             : 
     277             : //
     278             : // Accessors::StringLength
     279             : //
     280             : 
     281      144968 : void Accessors::StringLengthGetter(
     282             :     v8::Local<v8::Name> name,
     283             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     284             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     285             :   RuntimeCallTimerScope timer(isolate,
     286      144968 :                               RuntimeCallCounterId::kStringLengthGetter);
     287             :   DisallowHeapAllocation no_allocation;
     288             :   HandleScope scope(isolate);
     289             : 
     290             :   // We have a slight impedance mismatch between the external API and the way we
     291             :   // use callbacks internally: Externally, callbacks can only be used with
     292             :   // v8::Object, but internally we have callbacks on entities which are higher
     293             :   // in the hierarchy, in this case for String values.
     294             : 
     295      144968 :   Object value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
     296      144968 :   if (!value->IsString()) {
     297             :     // Not a string value. That means that we either got a String wrapper or
     298             :     // a Value with a String wrapper in its prototype chain.
     299        2773 :     value = JSValue::cast(*Utils::OpenHandle(*info.Holder()))->value();
     300             :   }
     301             :   Object result = Smi::FromInt(String::cast(value)->length());
     302             :   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
     303      144968 : }
     304             : 
     305          56 : Handle<AccessorInfo> Accessors::MakeStringLengthInfo(Isolate* isolate) {
     306             :   return MakeAccessor(isolate, isolate->factory()->length_string(),
     307          56 :                       &StringLengthGetter, nullptr);
     308             : }
     309             : 
     310             : //
     311             : // Accessors::FunctionPrototype
     312             : //
     313             : 
     314       85534 : static Handle<Object> GetFunctionPrototype(Isolate* isolate,
     315             :                                            Handle<JSFunction> function) {
     316       85534 :   if (!function->has_prototype()) {
     317       44389 :     Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
     318       44389 :     JSFunction::SetPrototype(function, proto);
     319             :   }
     320      171068 :   return Handle<Object>(function->prototype(), isolate);
     321             : }
     322             : 
     323       85534 : void Accessors::FunctionPrototypeGetter(
     324             :     v8::Local<v8::Name> name,
     325             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     326             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     327             :   RuntimeCallTimerScope timer(isolate,
     328       85534 :                               RuntimeCallCounterId::kFunctionPrototypeGetter);
     329             :   HandleScope scope(isolate);
     330             :   Handle<JSFunction> function =
     331       85534 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     332             :   DCHECK(function->has_prototype_property());
     333       85534 :   Handle<Object> result = GetFunctionPrototype(isolate, function);
     334             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     335       85534 : }
     336             : 
     337      135302 : void Accessors::FunctionPrototypeSetter(
     338             :     v8::Local<v8::Name> name, v8::Local<v8::Value> val,
     339             :     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     340             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     341             :   RuntimeCallTimerScope timer(isolate,
     342      135302 :                               RuntimeCallCounterId::kFunctionPrototypeSetter);
     343             :   HandleScope scope(isolate);
     344      135302 :   Handle<Object> value = Utils::OpenHandle(*val);
     345             :   Handle<JSFunction> object =
     346      135302 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     347             :   DCHECK(object->has_prototype_property());
     348      135302 :   JSFunction::SetPrototype(object, value);
     349             :   info.GetReturnValue().Set(true);
     350      135302 : }
     351             : 
     352          56 : Handle<AccessorInfo> Accessors::MakeFunctionPrototypeInfo(Isolate* isolate) {
     353             :   return MakeAccessor(isolate, isolate->factory()->prototype_string(),
     354          56 :                       &FunctionPrototypeGetter, &FunctionPrototypeSetter);
     355             : }
     356             : 
     357             : 
     358             : //
     359             : // Accessors::FunctionLength
     360             : //
     361             : 
     362             : 
     363       53918 : void Accessors::FunctionLengthGetter(
     364             :     v8::Local<v8::Name> name,
     365             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     366             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     367             :   RuntimeCallTimerScope timer(isolate,
     368       53918 :                               RuntimeCallCounterId::kFunctionLengthGetter);
     369             :   HandleScope scope(isolate);
     370             :   Handle<JSFunction> function =
     371       53918 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     372             :   int length = 0;
     373      107836 :   if (!JSFunction::GetLength(isolate, function).To(&length)) {
     374         335 :     isolate->OptionalRescheduleException(false);
     375             :   }
     376             :   Handle<Object> result(Smi::FromInt(length), isolate);
     377             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     378       53918 : }
     379             : 
     380          56 : Handle<AccessorInfo> Accessors::MakeFunctionLengthInfo(Isolate* isolate) {
     381             :   return MakeAccessor(isolate, isolate->factory()->length_string(),
     382          56 :                       &FunctionLengthGetter, &ReconfigureToDataProperty);
     383             : }
     384             : 
     385             : 
     386             : //
     387             : // Accessors::FunctionName
     388             : //
     389             : 
     390             : 
     391      110720 : void Accessors::FunctionNameGetter(
     392             :     v8::Local<v8::Name> name,
     393             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     394             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     395             :   HandleScope scope(isolate);
     396             :   Handle<JSFunction> function =
     397      110720 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     398      110720 :   Handle<Object> result = JSFunction::GetName(isolate, function);
     399             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     400      110720 : }
     401             : 
     402          56 : Handle<AccessorInfo> Accessors::MakeFunctionNameInfo(Isolate* isolate) {
     403             :   return MakeAccessor(isolate, isolate->factory()->name_string(),
     404          56 :                       &FunctionNameGetter, &ReconfigureToDataProperty);
     405             : }
     406             : 
     407             : 
     408             : //
     409             : // Accessors::FunctionArguments
     410             : //
     411             : 
     412             : namespace {
     413             : 
     414        2592 : Handle<JSObject> ArgumentsForInlinedFunction(JavaScriptFrame* frame,
     415             :                                              int inlined_frame_index) {
     416        5184 :   Isolate* isolate = frame->isolate();
     417             :   Factory* factory = isolate->factory();
     418             : 
     419        2592 :   TranslatedState translated_values(frame);
     420        2592 :   translated_values.Prepare(frame->fp());
     421             : 
     422        2592 :   int argument_count = 0;
     423             :   TranslatedFrame* translated_frame =
     424             :       translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index,
     425        2592 :                                                          &argument_count);
     426             :   TranslatedFrame::iterator iter = translated_frame->begin();
     427             : 
     428             :   // Materialize the function.
     429        2592 :   bool should_deoptimize = iter->IsMaterializedObject();
     430        2592 :   Handle<JSFunction> function = Handle<JSFunction>::cast(iter->GetValue());
     431        2592 :   iter++;
     432             : 
     433             :   // Skip the receiver.
     434        2592 :   iter++;
     435        2592 :   argument_count--;
     436             : 
     437             :   Handle<JSObject> arguments =
     438        2592 :       factory->NewArgumentsObject(function, argument_count);
     439        2592 :   Handle<FixedArray> array = factory->NewFixedArray(argument_count);
     440        9822 :   for (int i = 0; i < argument_count; ++i) {
     441             :     // If we materialize any object, we should deoptimize the frame because we
     442             :     // might alias an object that was eliminated by escape analysis.
     443       14404 :     should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
     444        7230 :     Handle<Object> value = iter->GetValue();
     445        7230 :     array->set(i, *value);
     446        7230 :     iter++;
     447             :   }
     448        5184 :   arguments->set_elements(*array);
     449             : 
     450        2592 :   if (should_deoptimize) {
     451         150 :     translated_values.StoreMaterializedValuesAndDeopt(frame);
     452             :   }
     453             : 
     454             :   // Return the freshly allocated arguments object.
     455        5184 :   return arguments;
     456             : }
     457             : 
     458      103518 : int FindFunctionInFrame(JavaScriptFrame* frame, Handle<JSFunction> function) {
     459             :   std::vector<FrameSummary> frames;
     460      103518 :   frame->Summarize(&frames);
     461      364505 :   for (size_t i = frames.size(); i != 0; i--) {
     462      213930 :     if (*frames[i - 1].AsJavaScript().function() == *function) {
     463       53014 :       return static_cast<int>(i) - 1;
     464             :     }
     465             :   }
     466      103518 :   return -1;
     467             : }
     468             : 
     469       63943 : Handle<JSObject> GetFrameArguments(Isolate* isolate,
     470             :                                    JavaScriptFrameIterator* it,
     471             :                                    int function_index) {
     472             :   JavaScriptFrame* frame = it->frame();
     473             : 
     474       63943 :   if (function_index > 0) {
     475             :     // The function in question was inlined.  Inlined functions have the
     476             :     // correct number of arguments and no allocated arguments object, so
     477             :     // we can construct a fresh one by interpreting the function's
     478             :     // deoptimization input data.
     479        2592 :     return ArgumentsForInlinedFunction(frame, function_index);
     480             :   }
     481             : 
     482             :   // Find the frame that holds the actual arguments passed to the function.
     483       61351 :   if (it->frame()->has_adapted_arguments()) {
     484             :     it->AdvanceOneFrame();
     485             :     DCHECK(it->frame()->is_arguments_adaptor());
     486             :   }
     487             :   frame = it->frame();
     488             : 
     489             :   // Get the number of arguments and construct an arguments object
     490             :   // mirror for the right frame and the underlying function.
     491       61351 :   const int length = frame->ComputeParametersCount();
     492       61351 :   Handle<JSFunction> function(frame->function(), isolate);
     493             :   Handle<JSObject> arguments =
     494       61351 :       isolate->factory()->NewArgumentsObject(function, length);
     495       61351 :   Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
     496             : 
     497             :   // Copy the parameters to the arguments object.
     498             :   DCHECK(array->length() == length);
     499      196257 :   for (int i = 0; i < length; i++) {
     500      134906 :     Object value = frame->GetParameter(i);
     501      134906 :     if (value->IsTheHole(isolate)) {
     502             :       // Generators currently use holes as dummy arguments when resuming.  We
     503             :       // must not leak those.
     504             :       DCHECK(IsResumableFunction(function->shared()->kind()));
     505           0 :       value = ReadOnlyRoots(isolate).undefined_value();
     506             :     }
     507      134906 :     array->set(i, value);
     508             :   }
     509      122702 :   arguments->set_elements(*array);
     510             : 
     511             :   // Return the freshly allocated arguments object.
     512       61351 :   return arguments;
     513             : }
     514             : 
     515             : }  // namespace
     516             : 
     517       10929 : Handle<JSObject> Accessors::FunctionGetArguments(JavaScriptFrame* frame,
     518             :                                                  int inlined_jsframe_index) {
     519       10929 :   Isolate* isolate = frame->isolate();
     520             :   Address requested_frame_fp = frame->fp();
     521             :   // Forward a frame iterator to the requested frame. This is needed because we
     522             :   // potentially need for advance it to the arguments adaptor frame later.
     523      217854 :   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
     524      108927 :     if (it.frame()->fp() != requested_frame_fp) continue;
     525       10929 :     return GetFrameArguments(isolate, &it, inlined_jsframe_index);
     526             :   }
     527           0 :   UNREACHABLE();  // Requested frame not found.
     528             :   return Handle<JSObject>();
     529             : }
     530             : 
     531             : 
     532       54108 : void Accessors::FunctionArgumentsGetter(
     533             :     v8::Local<v8::Name> name,
     534             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     535             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     536             :   HandleScope scope(isolate);
     537             :   Handle<JSFunction> function =
     538       54108 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     539             :   Handle<Object> result = isolate->factory()->null_value();
     540      108216 :   if (!function->shared()->native()) {
     541             :     // Find the top invocation of the function by traversing frames.
     542      209224 :     for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
     543             :       JavaScriptFrame* frame = it.frame();
     544      103518 :       int function_index = FindFunctionInFrame(frame, function);
     545      103518 :       if (function_index >= 0) {
     546       53014 :         result = GetFrameArguments(isolate, &it, function_index);
     547       53014 :         break;
     548             :       }
     549             :     }
     550             :   }
     551             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     552       54108 : }
     553             : 
     554          56 : Handle<AccessorInfo> Accessors::MakeFunctionArgumentsInfo(Isolate* isolate) {
     555             :   return MakeAccessor(isolate, isolate->factory()->arguments_string(),
     556          56 :                       &FunctionArgumentsGetter, nullptr);
     557             : }
     558             : 
     559             : 
     560             : //
     561             : // Accessors::FunctionCaller
     562             : //
     563             : 
     564             : static inline bool AllowAccessToFunction(Context current_context,
     565             :                                          JSFunction function) {
     566       17155 :   return current_context->HasSameSecurityTokenAs(function->context());
     567             : }
     568             : 
     569        3623 : class FrameFunctionIterator {
     570             :  public:
     571        3623 :   explicit FrameFunctionIterator(Isolate* isolate)
     572       10869 :       : isolate_(isolate), frame_iterator_(isolate), inlined_frame_index_(-1) {
     573             :     GetFrames();
     574        3623 :   }
     575             : 
     576             :   // Iterate through functions until the first occurrence of 'function'.
     577             :   // Returns true if one is found, and false if the iterator ends before.
     578        3623 :   bool Find(Handle<JSFunction> function) {
     579       10603 :     do {
     580       23430 :       if (!next().ToHandle(&function_)) return false;
     581             :     } while (!function_.is_identical_to(function));
     582             :     return true;
     583             :   }
     584             : 
     585             :   // Iterate through functions until the next non-toplevel one is found.
     586             :   // Returns true if one is found, and false if the iterator ends before.
     587        2511 :   bool FindNextNonTopLevel() {
     588        8766 :     do {
     589        8928 :       if (!next().ToHandle(&function_)) return false;
     590        8766 :     } while (function_->shared()->is_toplevel());
     591             :     return true;
     592             :   }
     593             : 
     594             :   // Iterate through function until the first native or user-provided function
     595             :   // is found. Functions not defined in user-provided scripts are not visible
     596             :   // unless directly exposed, in which case the native flag is set on them.
     597             :   // Returns true if one is found, and false if the iterator ends before.
     598        2430 :   bool FindFirstNativeOrUserJavaScript() {
     599       12051 :     while (!function_->shared()->native() &&
     600        4761 :            !function_->shared()->IsUserJavaScript()) {
     601           0 :       if (!next().ToHandle(&function_)) return false;
     602             :     }
     603             :     return true;
     604             :   }
     605             : 
     606             :   // In case of inlined frames the function could have been materialized from
     607             :   // deoptimization information. If that is the case we need to make sure that
     608             :   // subsequent call will see the same function, since we are about to hand out
     609             :   // the value to JavaScript. Make sure to store the materialized value and
     610             :   // trigger a deoptimization of the underlying frame.
     611        2430 :   Handle<JSFunction> MaterializeFunction() {
     612        2430 :     if (inlined_frame_index_ == 0) return function_;
     613             : 
     614             :     JavaScriptFrame* frame = frame_iterator_.frame();
     615          45 :     TranslatedState translated_values(frame);
     616          45 :     translated_values.Prepare(frame->fp());
     617             : 
     618             :     TranslatedFrame* translated_frame =
     619          45 :         translated_values.GetFrameFromJSFrameIndex(inlined_frame_index_);
     620             :     TranslatedFrame::iterator iter = translated_frame->begin();
     621             : 
     622             :     // First value is the function.
     623          45 :     bool should_deoptimize = iter->IsMaterializedObject();
     624          45 :     Handle<Object> value = iter->GetValue();
     625          45 :     if (should_deoptimize) {
     626          21 :       translated_values.StoreMaterializedValuesAndDeopt(frame);
     627             :     }
     628             : 
     629          45 :     return Handle<JSFunction>::cast(value);
     630             :   }
     631             : 
     632             :  private:
     633       16179 :   MaybeHandle<JSFunction> next() {
     634             :     while (true) {
     635       16206 :       if (inlined_frame_index_ <= 0) {
     636       10993 :         if (!frame_iterator_.done()) {
     637       10939 :           frame_iterator_.Advance();
     638       15013 :           frames_.clear();
     639       10939 :           inlined_frame_index_ = -1;
     640             :           GetFrames();
     641             :         }
     642       10993 :         if (inlined_frame_index_ == -1) return MaybeHandle<JSFunction>();
     643             :       }
     644             : 
     645       15013 :       --inlined_frame_index_;
     646             :       Handle<JSFunction> next_function =
     647       15013 :           frames_[inlined_frame_index_].AsJavaScript().function();
     648             :       // Skip functions from other origins.
     649       30026 :       if (!AllowAccessToFunction(isolate_->context(), *next_function)) continue;
     650       14986 :       return next_function;
     651             :     }
     652             :   }
     653             :   void GetFrames() {
     654             :     DCHECK_EQ(-1, inlined_frame_index_);
     655       14562 :     if (frame_iterator_.done()) return;
     656             :     JavaScriptFrame* frame = frame_iterator_.frame();
     657       13369 :     frame->Summarize(&frames_);
     658       13369 :     inlined_frame_index_ = static_cast<int>(frames_.size());
     659             :     DCHECK_LT(0, inlined_frame_index_);
     660             :   }
     661             :   Isolate* isolate_;
     662             :   Handle<JSFunction> function_;
     663             :   JavaScriptFrameIterator frame_iterator_;
     664             :   std::vector<FrameSummary> frames_;
     665             :   int inlined_frame_index_;
     666             : };
     667             : 
     668             : 
     669        3623 : MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
     670             :                                    Handle<JSFunction> function) {
     671        3623 :   FrameFunctionIterator it(isolate);
     672        7246 :   if (function->shared()->native()) {
     673           0 :     return MaybeHandle<JSFunction>();
     674             :   }
     675             :   // Find the function from the frames. Return null in case no frame
     676             :   // corresponding to the given function was found.
     677        3623 :   if (!it.Find(function)) {
     678        1112 :     return MaybeHandle<JSFunction>();
     679             :   }
     680             :   // Find previously called non-toplevel function.
     681        2511 :   if (!it.FindNextNonTopLevel()) {
     682          81 :     return MaybeHandle<JSFunction>();
     683             :   }
     684             :   // Find the first user-land JavaScript function (or the entry point into
     685             :   // native JavaScript builtins in case such a builtin was the caller).
     686        2430 :   if (!it.FindFirstNativeOrUserJavaScript()) {
     687           0 :     return MaybeHandle<JSFunction>();
     688             :   }
     689             : 
     690             :   // Materialize the function that the iterator is currently sitting on. Note
     691             :   // that this might trigger deoptimization in case the function was actually
     692             :   // materialized. Identity of the function must be preserved because we are
     693             :   // going to return it to JavaScript after this point.
     694        2430 :   Handle<JSFunction> caller = it.MaterializeFunction();
     695             : 
     696             :   // Censor if the caller is not a sloppy mode function.
     697             :   // Change from ES5, which used to throw, see:
     698             :   // https://bugs.ecmascript.org/show_bug.cgi?id=310
     699        2430 :   if (is_strict(caller->shared()->language_mode())) {
     700         288 :     return MaybeHandle<JSFunction>();
     701             :   }
     702             :   // Don't return caller from another security context.
     703        2142 :   if (!AllowAccessToFunction(isolate->context(), *caller)) {
     704           0 :     return MaybeHandle<JSFunction>();
     705             :   }
     706        2142 :   return caller;
     707             : }
     708             : 
     709             : 
     710        3623 : void Accessors::FunctionCallerGetter(
     711             :     v8::Local<v8::Name> name,
     712             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     713             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     714             :   HandleScope scope(isolate);
     715             :   Handle<JSFunction> function =
     716        3623 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     717             :   Handle<Object> result;
     718             :   MaybeHandle<JSFunction> maybe_caller;
     719        3623 :   maybe_caller = FindCaller(isolate, function);
     720             :   Handle<JSFunction> caller;
     721        3623 :   if (maybe_caller.ToHandle(&caller)) {
     722             :     result = caller;
     723             :   } else {
     724             :     result = isolate->factory()->null_value();
     725             :   }
     726             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     727        3623 : }
     728             : 
     729          56 : Handle<AccessorInfo> Accessors::MakeFunctionCallerInfo(Isolate* isolate) {
     730             :   return MakeAccessor(isolate, isolate->factory()->caller_string(),
     731          56 :                       &FunctionCallerGetter, nullptr);
     732             : }
     733             : 
     734             : 
     735             : //
     736             : // Accessors::BoundFunctionLength
     737             : //
     738             : 
     739         311 : void Accessors::BoundFunctionLengthGetter(
     740             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     741             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     742             :   RuntimeCallTimerScope timer(isolate,
     743         311 :                               RuntimeCallCounterId::kBoundFunctionLengthGetter);
     744             :   HandleScope scope(isolate);
     745             :   Handle<JSBoundFunction> function =
     746         311 :       Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
     747             : 
     748             :   int length = 0;
     749         622 :   if (!JSBoundFunction::GetLength(isolate, function).To(&length)) {
     750           0 :     isolate->OptionalRescheduleException(false);
     751         311 :     return;
     752             :   }
     753             :   Handle<Object> result(Smi::FromInt(length), isolate);
     754             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     755             : }
     756             : 
     757          56 : Handle<AccessorInfo> Accessors::MakeBoundFunctionLengthInfo(Isolate* isolate) {
     758             :   return MakeAccessor(isolate, isolate->factory()->length_string(),
     759          56 :                       &BoundFunctionLengthGetter, &ReconfigureToDataProperty);
     760             : }
     761             : 
     762             : //
     763             : // Accessors::BoundFunctionName
     764             : //
     765             : 
     766          77 : void Accessors::BoundFunctionNameGetter(
     767             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     768             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     769             :   RuntimeCallTimerScope timer(isolate,
     770          77 :                               RuntimeCallCounterId::kBoundFunctionNameGetter);
     771             :   HandleScope scope(isolate);
     772             :   Handle<JSBoundFunction> function =
     773          77 :       Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
     774             :   Handle<Object> result;
     775         154 :   if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) {
     776           0 :     isolate->OptionalRescheduleException(false);
     777          77 :     return;
     778             :   }
     779             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     780             : }
     781             : 
     782          56 : Handle<AccessorInfo> Accessors::MakeBoundFunctionNameInfo(Isolate* isolate) {
     783             :   return MakeAccessor(isolate, isolate->factory()->name_string(),
     784          56 :                       &BoundFunctionNameGetter, &ReconfigureToDataProperty);
     785             : }
     786             : 
     787             : //
     788             : // Accessors::ErrorStack
     789             : //
     790             : 
     791             : namespace {
     792             : 
     793       13902 : MaybeHandle<JSReceiver> ClearInternalStackTrace(Isolate* isolate,
     794             :                                                 Handle<JSObject> error) {
     795       27804 :   RETURN_ON_EXCEPTION(
     796             :       isolate,
     797             :       Object::SetProperty(
     798             :           isolate, error, isolate->factory()->stack_trace_symbol(),
     799             :           isolate->factory()->undefined_value(), LanguageMode::kStrict),
     800             :       JSReceiver);
     801       13902 :   return error;
     802             : }
     803             : 
     804       13822 : bool IsAccessor(Handle<Object> receiver, Handle<Name> name,
     805             :                 Handle<JSObject> holder) {
     806             :   LookupIterator it(receiver, name, holder,
     807       13822 :                     LookupIterator::OWN_SKIP_INTERCEPTOR);
     808             :   // Skip any access checks we might hit. This accessor should never hit in a
     809             :   // situation where the caller does not have access.
     810       13822 :   if (it.state() == LookupIterator::ACCESS_CHECK) {
     811           0 :     CHECK(it.HasAccess());
     812           0 :     it.Next();
     813             :   }
     814       13822 :   return (it.state() == LookupIterator::ACCESSOR);
     815             : }
     816             : 
     817             : }  // namespace
     818             : 
     819       13934 : void Accessors::ErrorStackGetter(
     820             :     v8::Local<v8::Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
     821             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     822             :   HandleScope scope(isolate);
     823             :   Handle<JSObject> holder =
     824       13934 :       Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
     825             : 
     826             :   // Retrieve the structured stack trace.
     827             : 
     828             :   Handle<Object> stack_trace;
     829             :   Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
     830             :   MaybeHandle<Object> maybe_stack_trace =
     831       13934 :       JSObject::GetProperty(isolate, holder, stack_trace_symbol);
     832       41802 :   if (!maybe_stack_trace.ToHandle(&stack_trace) ||
     833       41802 :       stack_trace->IsUndefined(isolate)) {
     834             :     Handle<Object> result = isolate->factory()->undefined_value();
     835             :     info.GetReturnValue().Set(Utils::ToLocal(result));
     836             :     return;
     837             :   }
     838             : 
     839             :   // Format it, clear the internal structured trace and reconfigure as a data
     840             :   // property.
     841             : 
     842             :   Handle<Object> formatted_stack_trace;
     843       13925 :   if (!ErrorUtils::FormatStackTrace(isolate, holder, stack_trace)
     844       27850 :            .ToHandle(&formatted_stack_trace)) {
     845         103 :     isolate->OptionalRescheduleException(false);
     846         103 :     return;
     847             :   }
     848             : 
     849       13822 :   MaybeHandle<Object> result = ClearInternalStackTrace(isolate, holder);
     850       13822 :   if (result.is_null()) {
     851           0 :     isolate->OptionalRescheduleException(false);
     852           0 :     return;
     853             :   }
     854             : 
     855             :   // If stack is still an accessor (this could have changed in the meantime
     856             :   // since FormatStackTrace can execute arbitrary JS), replace it with a data
     857             :   // property.
     858             :   Handle<Object> receiver =
     859       13822 :       Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
     860       13822 :   Handle<Name> name = Utils::OpenHandle(*key);
     861       13822 :   if (IsAccessor(receiver, name, holder)) {
     862             :     result = Accessors::ReplaceAccessorWithDataProperty(receiver, holder, name,
     863       13781 :                                                         formatted_stack_trace);
     864       13781 :     if (result.is_null()) {
     865           0 :       isolate->OptionalRescheduleException(false);
     866           0 :       return;
     867             :     }
     868             :   } else {
     869             :     // The stack property has been modified in the meantime.
     870          41 :     if (!JSObject::GetProperty(isolate, holder, name)
     871          82 :              .ToHandle(&formatted_stack_trace)) {
     872           0 :       isolate->OptionalRescheduleException(false);
     873           0 :       return;
     874             :     }
     875             :   }
     876             : 
     877             :   v8::Local<v8::Value> value = Utils::ToLocal(formatted_stack_trace);
     878             :   info.GetReturnValue().Set(value);
     879             : }
     880             : 
     881          80 : void Accessors::ErrorStackSetter(
     882             :     v8::Local<v8::Name> name, v8::Local<v8::Value> val,
     883             :     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     884             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     885             :   HandleScope scope(isolate);
     886             :   Handle<JSObject> obj = Handle<JSObject>::cast(
     887          80 :       Utils::OpenHandle(*v8::Local<v8::Value>(info.This())));
     888             : 
     889             :   // Clear internal properties to avoid memory leaks.
     890             :   Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
     891         160 :   if (JSReceiver::HasOwnProperty(obj, stack_trace_symbol).FromMaybe(false)) {
     892          80 :     ClearInternalStackTrace(isolate, obj);
     893             :   }
     894             : 
     895          80 :   Accessors::ReconfigureToDataProperty(name, val, info);
     896          80 : }
     897             : 
     898          56 : Handle<AccessorInfo> Accessors::MakeErrorStackInfo(Isolate* isolate) {
     899             :   return MakeAccessor(isolate, isolate->factory()->stack_string(),
     900          56 :                       &ErrorStackGetter, &ErrorStackSetter);
     901             : }
     902             : 
     903             : }  // namespace internal
     904      183867 : }  // namespace v8

Generated by: LCOV version 1.10