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

Generated by: LCOV version 1.10