LCOV - code coverage report
Current view: top level - src - accessors.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 258 271 95.2 %
Date: 2019-04-17 Functions: 45 45 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       31994 : Handle<AccessorInfo> Accessors::MakeAccessor(
      27             :     Isolate* isolate, Handle<Name> name, AccessorNameGetterCallback getter,
      28             :     AccessorNameBooleanSetterCallback setter) {
      29             :   Factory* factory = isolate->factory();
      30       31994 :   Handle<AccessorInfo> info = factory->NewAccessorInfo();
      31       31994 :   info->set_all_can_read(false);
      32       31994 :   info->set_all_can_write(false);
      33       31994 :   info->set_is_special_data_property(true);
      34       31994 :   info->set_is_sloppy(false);
      35       31994 :   info->set_replace_on_access(false);
      36       31994 :   info->set_getter_side_effect_type(SideEffectType::kHasSideEffect);
      37       31994 :   info->set_setter_side_effect_type(SideEffectType::kHasSideEffect);
      38       31994 :   name = factory->InternalizeName(name);
      39       31994 :   info->set_name(*name);
      40       31994 :   Handle<Object> get = v8::FromCData(isolate, getter);
      41       31994 :   if (setter == nullptr) setter = &ReconfigureToDataProperty;
      42       31994 :   Handle<Object> set = v8::FromCData(isolate, setter);
      43       31994 :   info->set_getter(*get);
      44       31994 :   info->set_setter(*set);
      45       31994 :   Address redirected = info->redirected_getter();
      46       31994 :   if (redirected != kNullAddress) {
      47       31014 :     Handle<Object> js_get = v8::FromCData(isolate, redirected);
      48       31014 :     info->set_js_getter(*js_get);
      49             :   }
      50       31994 :   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       75796 :   if (Name::Equals(isolate, name, property_name)) {
      58       65889 :     *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      267177 : bool Accessors::IsJSObjectFieldAccessor(Isolate* isolate, Handle<Map> map,
      68             :                                         Handle<Name> name, FieldIndex* index) {
      69      267177 :   switch (map->instance_type()) {
      70             :     case JS_ARRAY_TYPE:
      71             :       return CheckForName(isolate, name, isolate->factory()->length_string(),
      72       75664 :                           JSArray::kLengthOffset, FieldIndex::kTagged, index);
      73             :     default:
      74      191516 :       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        1469 : Accessors::ReplaceAccessorWithDataProperty(Handle<Object> receiver,
      85             :                                            Handle<JSObject> holder,
      86             :                                            Handle<Name> name,
      87             :                                            Handle<Object> value) {
      88             :   LookupIterator it(receiver, name, holder,
      89             :                     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        1469 :   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        1469 :   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
      98        1469 :   it.ReconfigureDataProperty(value, it.property_attributes());
      99        1469 :   return value;
     100             : }
     101             : 
     102             : 
     103             : //
     104             : // Accessors::ReconfigureToDataProperty
     105             : //
     106        1454 : 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        1454 :       isolate, RuntimeCallCounterId::kReconfigureToDataProperty);
     112             :   HandleScope scope(isolate);
     113             :   Handle<Object> receiver = Utils::OpenHandle(*info.This());
     114             :   Handle<JSObject> holder =
     115        1454 :       Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
     116        1454 :   Handle<Name> name = Utils::OpenHandle(*key);
     117        1454 :   Handle<Object> value = Utils::OpenHandle(*val);
     118             :   MaybeHandle<Object> result =
     119        1454 :       Accessors::ReplaceAccessorWithDataProperty(receiver, holder, name, value);
     120        1454 :   if (result.is_null()) {
     121           0 :     isolate->OptionalRescheduleException(false);
     122             :   } else {
     123             :     info.GetReturnValue().Set(true);
     124             :   }
     125        1454 : }
     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      136804 : 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      136804 :                               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      136803 : }
     165             : 
     166      478705 : 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      478705 :                               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             :   Handle<JSArray> array = Handle<JSArray>::cast(object);
     179      478705 :   Handle<Object> length_obj = Utils::OpenHandle(*val);
     180             : 
     181      478705 :   bool was_readonly = JSArray::HasReadOnlyLength(array);
     182             : 
     183      478705 :   uint32_t length = 0;
     184      478705 :   if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
     185         153 :     isolate->OptionalRescheduleException(false);
     186         153 :     return;
     187             :   }
     188             : 
     189      478570 :   if (!was_readonly && V8_UNLIKELY(JSArray::HasReadOnlyLength(array)) &&
     190          18 :       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          18 :       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      478534 :   JSArray::SetLength(array, length);
     208             : 
     209      478534 :   uint32_t actual_new_len = 0;
     210      957068 :   CHECK(array->length()->ToArrayLength(&actual_new_len));
     211             :   // Fail if there were non-deletable elements.
     212      478534 :   if (actual_new_len != length) {
     213          67 :     if (info.ShouldThrowOnError()) {
     214             :       Factory* factory = isolate->factory();
     215          54 :       isolate->Throw(*factory->NewTypeError(
     216             :           MessageTemplate::kStrictDeleteProperty,
     217          81 :           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       62470 :            ->GetExport(isolate, Handle<String>::cast(Utils::OpenHandle(*name)))
     245             :            .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             :       Handle<JSModuleNamespace>::cast(Utils::OpenHandle(*info.Holder()));
     260             : 
     261          45 :   if (info.ShouldThrowOnError()) {
     262          54 :     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       30393 : Handle<AccessorInfo> Accessors::MakeModuleNamespaceEntryInfo(
     272             :     Isolate* isolate, Handle<String> name) {
     273             :   return MakeAccessor(isolate, name, &ModuleNamespaceEntryGetter,
     274       30393 :                       &ModuleNamespaceEntrySetter);
     275             : }
     276             : 
     277             : 
     278             : //
     279             : // Accessors::StringLength
     280             : //
     281             : 
     282      146222 : 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      146222 :                               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             :   Object value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
     297      146222 :   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             :     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      146222 : }
     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       85373 : static Handle<Object> GetFunctionPrototype(Isolate* isolate,
     316             :                                            Handle<JSFunction> function) {
     317       85373 :   if (!function->has_prototype()) {
     318       45606 :     Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
     319       45606 :     JSFunction::SetPrototype(function, proto);
     320             :   }
     321      170746 :   return Handle<Object>(function->prototype(), isolate);
     322             : }
     323             : 
     324       85373 : 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       85373 :                               RuntimeCallCounterId::kFunctionPrototypeGetter);
     330             :   HandleScope scope(isolate);
     331             :   Handle<JSFunction> function =
     332       85373 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     333             :   DCHECK(function->has_prototype_property());
     334       85373 :   Handle<Object> result = GetFunctionPrototype(isolate, function);
     335             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     336       85373 : }
     337             : 
     338      135157 : 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      135157 :                               RuntimeCallCounterId::kFunctionPrototypeSetter);
     344             :   HandleScope scope(isolate);
     345      135157 :   Handle<Object> value = Utils::OpenHandle(*val);
     346             :   Handle<JSFunction> object =
     347      135157 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     348             :   DCHECK(object->has_prototype_property());
     349      135157 :   JSFunction::SetPrototype(object, value);
     350             :   info.GetReturnValue().Set(true);
     351      135157 : }
     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       53349 : 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       53349 :                               RuntimeCallCounterId::kFunctionLengthGetter);
     370             :   HandleScope scope(isolate);
     371             :   Handle<JSFunction> function =
     372             :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     373             :   int length = function->length();
     374             :   Handle<Object> result(Smi::FromInt(length), isolate);
     375             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     376       53349 : }
     377             : 
     378          56 : Handle<AccessorInfo> Accessors::MakeFunctionLengthInfo(Isolate* isolate) {
     379             :   return MakeAccessor(isolate, isolate->factory()->length_string(),
     380          56 :                       &FunctionLengthGetter, &ReconfigureToDataProperty);
     381             : }
     382             : 
     383             : 
     384             : //
     385             : // Accessors::FunctionName
     386             : //
     387             : 
     388             : 
     389      112987 : void Accessors::FunctionNameGetter(
     390             :     v8::Local<v8::Name> name,
     391             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     392             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     393             :   HandleScope scope(isolate);
     394             :   Handle<JSFunction> function =
     395      112987 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     396      112987 :   Handle<Object> result = JSFunction::GetName(isolate, function);
     397             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     398      112987 : }
     399             : 
     400          56 : Handle<AccessorInfo> Accessors::MakeFunctionNameInfo(Isolate* isolate) {
     401             :   return MakeAccessor(isolate, isolate->factory()->name_string(),
     402          56 :                       &FunctionNameGetter, &ReconfigureToDataProperty);
     403             : }
     404             : 
     405             : 
     406             : //
     407             : // Accessors::FunctionArguments
     408             : //
     409             : 
     410             : namespace {
     411             : 
     412        2573 : Handle<JSObject> ArgumentsForInlinedFunction(JavaScriptFrame* frame,
     413             :                                              int inlined_frame_index) {
     414             :   Isolate* isolate = frame->isolate();
     415             :   Factory* factory = isolate->factory();
     416             : 
     417        2573 :   TranslatedState translated_values(frame);
     418        2573 :   translated_values.Prepare(frame->fp());
     419             : 
     420        2573 :   int argument_count = 0;
     421             :   TranslatedFrame* translated_frame =
     422             :       translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index,
     423        2573 :                                                          &argument_count);
     424             :   TranslatedFrame::iterator iter = translated_frame->begin();
     425             : 
     426             :   // Materialize the function.
     427        2573 :   bool should_deoptimize = iter->IsMaterializedObject();
     428        2573 :   Handle<JSFunction> function = Handle<JSFunction>::cast(iter->GetValue());
     429             :   iter++;
     430             : 
     431             :   // Skip the receiver.
     432             :   iter++;
     433        2573 :   argument_count--;
     434             : 
     435             :   Handle<JSObject> arguments =
     436        2573 :       factory->NewArgumentsObject(function, argument_count);
     437        2573 :   Handle<FixedArray> array = factory->NewFixedArray(argument_count);
     438       17149 :   for (int i = 0; i < argument_count; ++i) {
     439             :     // If we materialize any object, we should deoptimize the frame because we
     440             :     // might alias an object that was eliminated by escape analysis.
     441        7288 :     should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
     442        7288 :     Handle<Object> value = iter->GetValue();
     443        7288 :     array->set(i, *value);
     444             :     iter++;
     445             :   }
     446        5146 :   arguments->set_elements(*array);
     447             : 
     448        2573 :   if (should_deoptimize) {
     449         158 :     translated_values.StoreMaterializedValuesAndDeopt(frame);
     450             :   }
     451             : 
     452             :   // Return the freshly allocated arguments object.
     453        5146 :   return arguments;
     454             : }
     455             : 
     456      105490 : int FindFunctionInFrame(JavaScriptFrame* frame, Handle<JSFunction> function) {
     457      105490 :   std::vector<FrameSummary> frames;
     458      105490 :   frame->Summarize(&frames);
     459      159827 :   for (size_t i = frames.size(); i != 0; i--) {
     460      215912 :     if (*frames[i - 1].AsJavaScript().function() == *function) {
     461       53619 :       return static_cast<int>(i) - 1;
     462             :     }
     463             :   }
     464             :   return -1;
     465             : }
     466             : 
     467       64647 : Handle<JSObject> GetFrameArguments(Isolate* isolate,
     468             :                                    JavaScriptFrameIterator* it,
     469             :                                    int function_index) {
     470             :   JavaScriptFrame* frame = it->frame();
     471             : 
     472       64647 :   if (function_index > 0) {
     473             :     // The function in question was inlined.  Inlined functions have the
     474             :     // correct number of arguments and no allocated arguments object, so
     475             :     // we can construct a fresh one by interpreting the function's
     476             :     // deoptimization input data.
     477        2573 :     return ArgumentsForInlinedFunction(frame, function_index);
     478             :   }
     479             : 
     480             :   // Find the frame that holds the actual arguments passed to the function.
     481       62074 :   if (it->frame()->has_adapted_arguments()) {
     482             :     it->AdvanceOneFrame();
     483             :     DCHECK(it->frame()->is_arguments_adaptor());
     484             :   }
     485             :   frame = it->frame();
     486             : 
     487             :   // Get the number of arguments and construct an arguments object
     488             :   // mirror for the right frame and the underlying function.
     489       62074 :   const int length = frame->ComputeParametersCount();
     490       62074 :   Handle<JSFunction> function(frame->function(), isolate);
     491             :   Handle<JSObject> arguments =
     492       62074 :       isolate->factory()->NewArgumentsObject(function, length);
     493       62074 :   Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
     494             : 
     495             :   // Copy the parameters to the arguments object.
     496             :   DCHECK(array->length() == length);
     497      335352 :   for (int i = 0; i < length; i++) {
     498      136639 :     Object value = frame->GetParameter(i);
     499      136639 :     if (value->IsTheHole(isolate)) {
     500             :       // Generators currently use holes as dummy arguments when resuming.  We
     501             :       // must not leak those.
     502             :       DCHECK(IsResumableFunction(function->shared()->kind()));
     503             :       value = ReadOnlyRoots(isolate).undefined_value();
     504             :     }
     505      136639 :     array->set(i, value);
     506             :   }
     507      124148 :   arguments->set_elements(*array);
     508             : 
     509             :   // Return the freshly allocated arguments object.
     510       62074 :   return arguments;
     511             : }
     512             : 
     513             : }  // namespace
     514             : 
     515       11028 : Handle<JSObject> Accessors::FunctionGetArguments(JavaScriptFrame* frame,
     516             :                                                  int inlined_jsframe_index) {
     517             :   Isolate* isolate = frame->isolate();
     518             :   Address requested_frame_fp = frame->fp();
     519             :   // Forward a frame iterator to the requested frame. This is needed because we
     520             :   // potentially need for advance it to the arguments adaptor frame later.
     521      110501 :   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
     522      110501 :     if (it.frame()->fp() != requested_frame_fp) continue;
     523       11028 :     return GetFrameArguments(isolate, &it, inlined_jsframe_index);
     524             :   }
     525           0 :   UNREACHABLE();  // Requested frame not found.
     526             :   return Handle<JSObject>();
     527             : }
     528             : 
     529             : 
     530       54714 : void Accessors::FunctionArgumentsGetter(
     531             :     v8::Local<v8::Name> name,
     532             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     533             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     534             :   HandleScope scope(isolate);
     535             :   Handle<JSFunction> function =
     536             :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     537             :   Handle<Object> result = isolate->factory()->null_value();
     538       54714 :   if (!function->shared()->native()) {
     539             :     // Find the top invocation of the function by traversing frames.
     540      106585 :     for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
     541             :       JavaScriptFrame* frame = it.frame();
     542      105490 :       int function_index = FindFunctionInFrame(frame, function);
     543      105490 :       if (function_index >= 0) {
     544       53619 :         result = GetFrameArguments(isolate, &it, function_index);
     545       53619 :         break;
     546             :       }
     547             :     }
     548             :   }
     549             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     550       54714 : }
     551             : 
     552          56 : Handle<AccessorInfo> Accessors::MakeFunctionArgumentsInfo(Isolate* isolate) {
     553             :   return MakeAccessor(isolate, isolate->factory()->arguments_string(),
     554          56 :                       &FunctionArgumentsGetter, nullptr);
     555             : }
     556             : 
     557             : 
     558             : //
     559             : // Accessors::FunctionCaller
     560             : //
     561             : 
     562             : static inline bool AllowAccessToFunction(Context current_context,
     563             :                                          JSFunction function) {
     564       17476 :   return current_context->HasSameSecurityTokenAs(function->context());
     565             : }
     566             : 
     567        7578 : class FrameFunctionIterator {
     568             :  public:
     569        3789 :   explicit FrameFunctionIterator(Isolate* isolate)
     570       11367 :       : isolate_(isolate), frame_iterator_(isolate), inlined_frame_index_(-1) {
     571             :     GetFrames();
     572        3789 :   }
     573             : 
     574             :   // Iterate through functions until the first occurrence of 'function'.
     575             :   // Returns true if one is found, and false if the iterator ends before.
     576        3789 :   bool Find(Handle<JSFunction> function) {
     577       10564 :     do {
     578       23324 :       if (!next().ToHandle(&function_)) return false;
     579             :     } while (!function_.is_identical_to(function));
     580             :     return true;
     581             :   }
     582             : 
     583             :   // Iterate through functions until the next non-toplevel one is found.
     584             :   // Returns true if one is found, and false if the iterator ends before.
     585        2691 :   bool FindNextNonTopLevel() {
     586        4563 :     do {
     587        9288 :       if (!next().ToHandle(&function_)) return false;
     588             :     } while (function_->shared()->is_toplevel());
     589             :     return true;
     590             :   }
     591             : 
     592             :   // Iterate through function until the first native or user-provided function
     593             :   // is found. Functions not defined in user-provided scripts are not visible
     594             :   // unless directly exposed, in which case the native flag is set on them.
     595             :   // Returns true if one is found, and false if the iterator ends before.
     596        2610 :   bool FindFirstNativeOrUserJavaScript() {
     597        7731 :     while (!function_->shared()->native() &&
     598        5121 :            !function_->shared()->IsUserJavaScript()) {
     599           0 :       if (!next().ToHandle(&function_)) return false;
     600             :     }
     601             :     return true;
     602             :   }
     603             : 
     604             :   // In case of inlined frames the function could have been materialized from
     605             :   // deoptimization information. If that is the case we need to make sure that
     606             :   // subsequent call will see the same function, since we are about to hand out
     607             :   // the value to JavaScript. Make sure to store the materialized value and
     608             :   // trigger a deoptimization of the underlying frame.
     609        2610 :   Handle<JSFunction> MaterializeFunction() {
     610        2610 :     if (inlined_frame_index_ == 0) return function_;
     611             : 
     612             :     JavaScriptFrame* frame = frame_iterator_.frame();
     613          45 :     TranslatedState translated_values(frame);
     614          45 :     translated_values.Prepare(frame->fp());
     615             : 
     616             :     TranslatedFrame* translated_frame =
     617          45 :         translated_values.GetFrameFromJSFrameIndex(inlined_frame_index_);
     618             :     TranslatedFrame::iterator iter = translated_frame->begin();
     619             : 
     620             :     // First value is the function.
     621          45 :     bool should_deoptimize = iter->IsMaterializedObject();
     622          45 :     Handle<Object> value = iter->GetValue();
     623          45 :     if (should_deoptimize) {
     624          24 :       translated_values.StoreMaterializedValuesAndDeopt(frame);
     625             :     }
     626             : 
     627             :     return Handle<JSFunction>::cast(value);
     628             :   }
     629             : 
     630             :  private:
     631       16306 :   MaybeHandle<JSFunction> next() {
     632             :     while (true) {
     633       16333 :       if (inlined_frame_index_ <= 0) {
     634       11801 :         if (!frame_iterator_.done()) {
     635       11747 :           frame_iterator_.Advance();
     636             :           frames_.clear();
     637       11747 :           inlined_frame_index_ = -1;
     638             :           GetFrames();
     639             :         }
     640       11801 :         if (inlined_frame_index_ == -1) return MaybeHandle<JSFunction>();
     641             :       }
     642             : 
     643       15154 :       --inlined_frame_index_;
     644             :       Handle<JSFunction> next_function =
     645       15154 :           frames_[inlined_frame_index_].AsJavaScript().function();
     646             :       // Skip functions from other origins.
     647       30308 :       if (!AllowAccessToFunction(isolate_->context(), *next_function)) continue;
     648       15127 :       return next_function;
     649             :     }
     650             :   }
     651             :   void GetFrames() {
     652             :     DCHECK_EQ(-1, inlined_frame_index_);
     653       15536 :     if (frame_iterator_.done()) return;
     654             :     JavaScriptFrame* frame = frame_iterator_.frame();
     655       14357 :     frame->Summarize(&frames_);
     656       14357 :     inlined_frame_index_ = static_cast<int>(frames_.size());
     657             :     DCHECK_LT(0, inlined_frame_index_);
     658             :   }
     659             :   Isolate* isolate_;
     660             :   Handle<JSFunction> function_;
     661             :   JavaScriptFrameIterator frame_iterator_;
     662             :   std::vector<FrameSummary> frames_;
     663             :   int inlined_frame_index_;
     664             : };
     665             : 
     666             : 
     667        3789 : MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
     668             :                                    Handle<JSFunction> function) {
     669        3789 :   FrameFunctionIterator it(isolate);
     670        3789 :   if (function->shared()->native()) {
     671           0 :     return MaybeHandle<JSFunction>();
     672             :   }
     673             :   // Find the function from the frames. Return null in case no frame
     674             :   // corresponding to the given function was found.
     675        3789 :   if (!it.Find(function)) {
     676        1098 :     return MaybeHandle<JSFunction>();
     677             :   }
     678             :   // Find previously called non-toplevel function.
     679        2691 :   if (!it.FindNextNonTopLevel()) {
     680          81 :     return MaybeHandle<JSFunction>();
     681             :   }
     682             :   // Find the first user-land JavaScript function (or the entry point into
     683             :   // native JavaScript builtins in case such a builtin was the caller).
     684        2610 :   if (!it.FindFirstNativeOrUserJavaScript()) {
     685           0 :     return MaybeHandle<JSFunction>();
     686             :   }
     687             : 
     688             :   // Materialize the function that the iterator is currently sitting on. Note
     689             :   // that this might trigger deoptimization in case the function was actually
     690             :   // materialized. Identity of the function must be preserved because we are
     691             :   // going to return it to JavaScript after this point.
     692        2610 :   Handle<JSFunction> caller = it.MaterializeFunction();
     693             : 
     694             :   // Censor if the caller is not a sloppy mode function.
     695             :   // Change from ES5, which used to throw, see:
     696             :   // https://bugs.ecmascript.org/show_bug.cgi?id=310
     697        2610 :   if (is_strict(caller->shared()->language_mode())) {
     698         288 :     return MaybeHandle<JSFunction>();
     699             :   }
     700             :   // Don't return caller from another security context.
     701        2322 :   if (!AllowAccessToFunction(isolate->context(), *caller)) {
     702           0 :     return MaybeHandle<JSFunction>();
     703             :   }
     704        2322 :   return caller;
     705             : }
     706             : 
     707             : 
     708        3789 : void Accessors::FunctionCallerGetter(
     709             :     v8::Local<v8::Name> name,
     710             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     711             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     712             :   HandleScope scope(isolate);
     713             :   Handle<JSFunction> function =
     714        3789 :       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
     715             :   Handle<Object> result;
     716             :   MaybeHandle<JSFunction> maybe_caller;
     717        3789 :   maybe_caller = FindCaller(isolate, function);
     718             :   Handle<JSFunction> caller;
     719        3789 :   if (maybe_caller.ToHandle(&caller)) {
     720             :     result = caller;
     721             :   } else {
     722             :     result = isolate->factory()->null_value();
     723             :   }
     724             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     725        3789 : }
     726             : 
     727          56 : Handle<AccessorInfo> Accessors::MakeFunctionCallerInfo(Isolate* isolate) {
     728             :   return MakeAccessor(isolate, isolate->factory()->caller_string(),
     729          56 :                       &FunctionCallerGetter, nullptr);
     730             : }
     731             : 
     732             : 
     733             : //
     734             : // Accessors::BoundFunctionLength
     735             : //
     736             : 
     737         316 : void Accessors::BoundFunctionLengthGetter(
     738             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     739             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     740             :   RuntimeCallTimerScope timer(isolate,
     741         316 :                               RuntimeCallCounterId::kBoundFunctionLengthGetter);
     742             :   HandleScope scope(isolate);
     743             :   Handle<JSBoundFunction> function =
     744         316 :       Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
     745             : 
     746             :   int length = 0;
     747         632 :   if (!JSBoundFunction::GetLength(isolate, function).To(&length)) {
     748           0 :     isolate->OptionalRescheduleException(false);
     749             :     return;
     750             :   }
     751             :   Handle<Object> result(Smi::FromInt(length), isolate);
     752             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     753             : }
     754             : 
     755          56 : Handle<AccessorInfo> Accessors::MakeBoundFunctionLengthInfo(Isolate* isolate) {
     756             :   return MakeAccessor(isolate, isolate->factory()->length_string(),
     757          56 :                       &BoundFunctionLengthGetter, &ReconfigureToDataProperty);
     758             : }
     759             : 
     760             : //
     761             : // Accessors::BoundFunctionName
     762             : //
     763             : 
     764          82 : void Accessors::BoundFunctionNameGetter(
     765             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     766             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     767             :   RuntimeCallTimerScope timer(isolate,
     768          82 :                               RuntimeCallCounterId::kBoundFunctionNameGetter);
     769             :   HandleScope scope(isolate);
     770             :   Handle<JSBoundFunction> function =
     771          82 :       Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
     772             :   Handle<Object> result;
     773         164 :   if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) {
     774           0 :     isolate->OptionalRescheduleException(false);
     775             :     return;
     776             :   }
     777             :   info.GetReturnValue().Set(Utils::ToLocal(result));
     778             : }
     779             : 
     780          56 : Handle<AccessorInfo> Accessors::MakeBoundFunctionNameInfo(Isolate* isolate) {
     781             :   return MakeAccessor(isolate, isolate->factory()->name_string(),
     782          56 :                       &BoundFunctionNameGetter, &ReconfigureToDataProperty);
     783             : }
     784             : 
     785             : //
     786             : // Accessors::ErrorStack
     787             : //
     788             : 
     789       18722 : void Accessors::ErrorStackGetter(
     790             :     v8::Local<v8::Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
     791             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     792             :   HandleScope scope(isolate);
     793             :   Handle<JSObject> holder =
     794             :       Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
     795             : 
     796             :   // Retrieve the stack trace. It can either be structured data in the form of
     797             :   // a FrameArray, an already formatted stack trace (string) or whatever the
     798             :   // "prepareStackTrace" callback produced.
     799             : 
     800             :   Handle<Object> stack_trace;
     801             :   Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
     802             :   MaybeHandle<Object> maybe_stack_trace =
     803       18722 :       JSObject::GetProperty(isolate, holder, stack_trace_symbol);
     804       37444 :   if (!maybe_stack_trace.ToHandle(&stack_trace) ||
     805             :       stack_trace->IsUndefined(isolate)) {
     806             :     Handle<Object> result = isolate->factory()->undefined_value();
     807             :     info.GetReturnValue().Set(Utils::ToLocal(result));
     808             :     return;
     809             :   }
     810             : 
     811             :   // Only format the stack-trace the first time around. The check for a
     812             :   // FixedArray is sufficient as the user callback can not create plain
     813             :   // FixedArrays and the result is a String in case we format the stack
     814             :   // trace ourselves.
     815             : 
     816       18704 :   if (!stack_trace->IsFixedArray()) {
     817             :     info.GetReturnValue().Set(Utils::ToLocal(stack_trace));
     818             :     return;
     819             :   }
     820             : 
     821             :   Handle<Object> formatted_stack_trace;
     822       30670 :   if (!ErrorUtils::FormatStackTrace(isolate, holder, stack_trace)
     823             :            .ToHandle(&formatted_stack_trace)) {
     824         116 :     isolate->OptionalRescheduleException(false);
     825         116 :     return;
     826             :   }
     827             : 
     828             :   // Replace the structured stack-trace with the formatting result.
     829             :   MaybeHandle<Object> result = Object::SetProperty(
     830             :       isolate, holder, isolate->factory()->stack_trace_symbol(),
     831             :       formatted_stack_trace, StoreOrigin::kMaybeKeyed,
     832       15219 :       Just(ShouldThrow::kThrowOnError));
     833       15219 :   if (result.is_null()) {
     834           0 :     isolate->OptionalRescheduleException(false);
     835           0 :     return;
     836             :   }
     837             : 
     838             :   v8::Local<v8::Value> value = Utils::ToLocal(formatted_stack_trace);
     839             :   info.GetReturnValue().Set(value);
     840             : }
     841             : 
     842         167 : void Accessors::ErrorStackSetter(
     843             :     v8::Local<v8::Name> name, v8::Local<v8::Value> val,
     844             :     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     845             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
     846             :   HandleScope scope(isolate);
     847             :   Handle<JSObject> obj = Handle<JSObject>::cast(
     848             :       Utils::OpenHandle(*v8::Local<v8::Value>(info.This())));
     849         167 :   Handle<Object> value = Handle<Object>::cast(Utils::OpenHandle(*val));
     850             : 
     851             :   // Store the value in the internal symbol to avoid reconfiguration to
     852             :   // a data property.
     853             :   MaybeHandle<Object> result = Object::SetProperty(
     854             :       isolate, obj, isolate->factory()->stack_trace_symbol(), value,
     855         167 :       StoreOrigin::kMaybeKeyed, Just(ShouldThrow::kThrowOnError));
     856         167 :   if (result.is_null()) {
     857           0 :     isolate->OptionalRescheduleException(false);
     858             :     return;
     859             :   }
     860             : }
     861             : 
     862          56 : Handle<AccessorInfo> Accessors::MakeErrorStackInfo(Isolate* isolate) {
     863             :   return MakeAccessor(isolate, isolate->factory()->stack_string(),
     864          56 :                       &ErrorStackGetter, &ErrorStackSetter);
     865             : }
     866             : 
     867             : }  // namespace internal
     868      122004 : }  // namespace v8

Generated by: LCOV version 1.10