LCOV - code coverage report
Current view: top level - src/runtime - runtime-scopes.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 362 376 96.3 %
Date: 2017-04-26 Functions: 37 62 59.7 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/runtime/runtime-utils.h"
       6             : 
       7             : #include <memory>
       8             : 
       9             : #include "src/accessors.h"
      10             : #include "src/arguments.h"
      11             : #include "src/ast/scopes.h"
      12             : #include "src/deoptimizer.h"
      13             : #include "src/frames-inl.h"
      14             : #include "src/isolate-inl.h"
      15             : #include "src/messages.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20       73702 : RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) {
      21       36851 :   HandleScope scope(isolate);
      22       73702 :   THROW_NEW_ERROR_RETURN_FAILURE(isolate,
      23       36851 :                                  NewTypeError(MessageTemplate::kConstAssign));
      24             : }
      25             : 
      26             : namespace {
      27             : 
      28             : enum class RedeclarationType { kSyntaxError = 0, kTypeError = 1 };
      29             : 
      30         483 : Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name,
      31             :                                 RedeclarationType redeclaration_type) {
      32             :   HandleScope scope(isolate);
      33         483 :   if (redeclaration_type == RedeclarationType::kSyntaxError) {
      34         846 :     THROW_NEW_ERROR_RETURN_FAILURE(
      35             :         isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name));
      36             :   } else {
      37         120 :     THROW_NEW_ERROR_RETURN_FAILURE(
      38             :         isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
      39             :   }
      40             : }
      41             : 
      42             : 
      43             : // May throw a RedeclarationError.
      44     2230969 : Object* DeclareGlobal(
      45             :     Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name,
      46             :     Handle<Object> value, PropertyAttributes attr, bool is_var,
      47             :     bool is_function_declaration, RedeclarationType redeclaration_type,
      48             :     Handle<FeedbackVector> feedback_vector = Handle<FeedbackVector>(),
      49             :     FeedbackSlot slot = FeedbackSlot::Invalid()) {
      50             :   Handle<ScriptContextTable> script_contexts(
      51             :       global->native_context()->script_context_table());
      52             :   ScriptContextTable::LookupResult lookup;
      53     2231008 :   if (ScriptContextTable::Lookup(script_contexts, name, &lookup) &&
      54          39 :       IsLexicalVariableMode(lookup.mode)) {
      55             :     // ES#sec-globaldeclarationinstantiation 6.a:
      56             :     // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
      57             :     // exception.
      58             :     return ThrowRedeclarationError(isolate, name,
      59          39 :                                    RedeclarationType::kSyntaxError);
      60             :   }
      61             : 
      62             :   // Do the lookup own properties only, see ES5 erratum.
      63             :   LookupIterator::Configuration lookup_config(
      64             :       LookupIterator::Configuration::OWN_SKIP_INTERCEPTOR);
      65     2230930 :   if (is_function_declaration) {
      66             :     // For function declarations, use the interceptor on the declaration. For
      67             :     // non-functions, use it only on initialization.
      68             :     lookup_config = LookupIterator::Configuration::OWN;
      69             :   }
      70     2230930 :   LookupIterator it(global, name, global, lookup_config);
      71     2230930 :   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
      72     2230930 :   if (!maybe.IsJust()) return isolate->heap()->exception();
      73             : 
      74     2230930 :   if (it.IsFound()) {
      75             :     PropertyAttributes old_attributes = maybe.FromJust();
      76             :     // The name was declared before; check for conflicting re-declarations.
      77             : 
      78             :     // Skip var re-declarations.
      79      261732 :     if (is_var) return isolate->heap()->undefined_value();
      80             : 
      81             :     DCHECK(is_function_declaration);
      82       38220 :     if ((old_attributes & DONT_DELETE) != 0) {
      83             :       // Only allow reconfiguring globals to functions in user code (no
      84             :       // natives, which are marked as read-only).
      85             :       DCHECK((attr & READ_ONLY) == 0);
      86             : 
      87             :       // Check whether we can reconfigure the existing property into a
      88             :       // function.
      89       68262 :       if (old_attributes & READ_ONLY || old_attributes & DONT_ENUM ||
      90       34090 :           (it.state() == LookupIterator::ACCESSOR)) {
      91             :         // ECMA-262 section 15.1.11 GlobalDeclarationInstantiation 5.d:
      92             :         // If hasRestrictedGlobal is true, throw a SyntaxError exception.
      93             :         // ECMA-262 section 18.2.1.3 EvalDeclarationInstantiation 8.a.iv.1.b:
      94             :         // If fnDefinable is false, throw a TypeError exception.
      95          89 :         return ThrowRedeclarationError(isolate, name, redeclaration_type);
      96             :       }
      97             :       // If the existing property is not configurable, keep its attributes. Do
      98             :       attr = old_attributes;
      99             :     }
     100             : 
     101             :     // If the current state is ACCESSOR, this could mean it's an AccessorInfo
     102             :     // type property. We are not allowed to call into such setters during global
     103             :     // function declaration since this would break e.g., onload. Meaning
     104             :     // 'function onload() {}' would invalidly register that function as the
     105             :     // onload callback. To avoid this situation, we first delete the property
     106             :     // before readding it as a regular data property below.
     107       38131 :     if (it.state() == LookupIterator::ACCESSOR) it.Delete();
     108             :   }
     109             : 
     110     2007329 :   if (is_function_declaration) {
     111      411196 :     it.Restart();
     112             :   }
     113             : 
     114             :   // Define or redefine own property.
     115     4014658 :   RETURN_FAILURE_ON_EXCEPTION(
     116             :       isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr));
     117             : 
     118     4009267 :   if (!feedback_vector.is_null() &&
     119     2001952 :       it.state() != LookupIterator::State::INTERCEPTOR) {
     120             :     DCHECK_EQ(*global, *it.GetHolder<Object>());
     121             :     // Preinitialize the feedback slot if the global object does not have
     122             :     // named interceptor or the interceptor is not masking.
     123     2002259 :     if (!global->HasNamedInterceptor() ||
     124         314 :         global->GetNamedInterceptor()->non_masking()) {
     125             :       LoadGlobalICNexus nexus(feedback_vector, slot);
     126     2001631 :       nexus.ConfigurePropertyCellMode(it.GetPropertyCell());
     127             :     }
     128             :   }
     129     2007315 :   return isolate->heap()->undefined_value();
     130             : }
     131             : 
     132      349044 : Object* DeclareGlobals(Isolate* isolate, Handle<FixedArray> declarations,
     133             :                        int flags, Handle<FeedbackVector> feedback_vector) {
     134             :   HandleScope scope(isolate);
     135      174522 :   Handle<JSGlobalObject> global(isolate->global_object());
     136             :   Handle<Context> context(isolate->context());
     137             : 
     138             :   // Traverse the name/value pairs and set the properties.
     139             :   int length = declarations->length();
     140    14777043 :   FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 4, {
     141             :     Handle<String> name(String::cast(declarations->get(i)), isolate);
     142             :     FeedbackSlot slot(Smi::cast(declarations->get(i + 1))->value());
     143             :     Handle<Object> possibly_literal_slot(declarations->get(i + 2), isolate);
     144             :     Handle<Object> initial_value(declarations->get(i + 3), isolate);
     145             : 
     146             :     bool is_var = initial_value->IsUndefined(isolate);
     147             :     bool is_function = initial_value->IsSharedFunctionInfo();
     148             :     DCHECK_EQ(1, BoolToInt(is_var) + BoolToInt(is_function));
     149             : 
     150             :     Handle<Object> value;
     151             :     if (is_function) {
     152             :       DCHECK(possibly_literal_slot->IsSmi());
     153             :       // Copy the function and update its context. Use it as value.
     154             :       Handle<SharedFunctionInfo> shared =
     155             :           Handle<SharedFunctionInfo>::cast(initial_value);
     156             :       FeedbackSlot literals_slot(Smi::cast(*possibly_literal_slot)->value());
     157             :       Handle<Cell> literals(Cell::cast(feedback_vector->Get(literals_slot)),
     158             :                             isolate);
     159             :       Handle<JSFunction> function =
     160             :           isolate->factory()->NewFunctionFromSharedFunctionInfo(
     161             :               shared, context, literals, TENURED);
     162             :       value = function;
     163             :     } else {
     164             :       value = isolate->factory()->undefined_value();
     165             :     }
     166             : 
     167             :     // Compute the property attributes. According to ECMA-262,
     168             :     // the property must be non-configurable except in eval.
     169             :     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
     170             :     bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
     171             :     int attr = NONE;
     172             :     if (is_function && is_native) attr |= READ_ONLY;
     173             :     if (!is_eval) attr |= DONT_DELETE;
     174             : 
     175             :     // ES#sec-globaldeclarationinstantiation 5.d:
     176             :     // If hasRestrictedGlobal is true, throw a SyntaxError exception.
     177             :     Object* result = DeclareGlobal(
     178             :         isolate, global, name, value, static_cast<PropertyAttributes>(attr),
     179             :         is_var, is_function, RedeclarationType::kSyntaxError, feedback_vector,
     180             :         slot);
     181             :     if (isolate->has_pending_exception()) return result;
     182             :   });
     183             : 
     184      174454 :   return isolate->heap()->undefined_value();
     185             : }
     186             : 
     187             : }  // namespace
     188             : 
     189      115004 : RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
     190       57502 :   HandleScope scope(isolate);
     191             :   DCHECK_EQ(3, args.length());
     192             : 
     193      115004 :   CONVERT_ARG_HANDLE_CHECKED(FixedArray, declarations, 0);
     194      115004 :   CONVERT_SMI_ARG_CHECKED(flags, 1);
     195      115004 :   CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, feedback_vector, 2);
     196             : 
     197       57502 :   return DeclareGlobals(isolate, declarations, flags, feedback_vector);
     198             : }
     199             : 
     200             : // TODO(ishell): merge this with Runtime::kDeclareGlobals once interpreter
     201             : // is able to pass feedback vector.
     202      234040 : RUNTIME_FUNCTION(Runtime_DeclareGlobalsForInterpreter) {
     203      117020 :   HandleScope scope(isolate);
     204             :   DCHECK_EQ(3, args.length());
     205             : 
     206      234040 :   CONVERT_ARG_HANDLE_CHECKED(FixedArray, declarations, 0);
     207      234040 :   CONVERT_SMI_ARG_CHECKED(flags, 1);
     208      234040 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 2);
     209             : 
     210      117020 :   Handle<FeedbackVector> feedback_vector(closure->feedback_vector(), isolate);
     211      117020 :   return DeclareGlobals(isolate, declarations, flags, feedback_vector);
     212             : }
     213             : 
     214      407148 : RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
     215      203574 :   HandleScope scope(isolate);
     216             :   DCHECK_EQ(3, args.length());
     217      407148 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
     218      407148 :   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1);
     219      203574 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
     220             : 
     221      203574 :   Handle<JSGlobalObject> global(isolate->global_object());
     222      407148 :   RETURN_RESULT_OR_FAILURE(
     223      203574 :       isolate, Object::SetProperty(global, name, value, language_mode));
     224             : }
     225             : 
     226             : namespace {
     227             : 
     228      504173 : Object* DeclareEvalHelper(Isolate* isolate, Handle<String> name,
     229             :                           Handle<Object> value) {
     230             :   // Declarations are always made in a function, native, eval, or script
     231             :   // context, or a declaration block scope. Since this is called from eval, the
     232             :   // context passed is the context of the caller, which may be some nested
     233             :   // context and not the declaration context.
     234             :   Handle<Context> context_arg(isolate->context(), isolate);
     235      504173 :   Handle<Context> context(context_arg->declaration_context(), isolate);
     236             : 
     237             :   DCHECK(context->IsFunctionContext() || context->IsNativeContext() ||
     238             :          context->IsScriptContext() || context->IsEvalContext() ||
     239             :          (context->IsBlockContext() && context->has_extension()));
     240             : 
     241             :   bool is_function = value->IsJSFunction();
     242      504173 :   bool is_var = !is_function;
     243             :   DCHECK(!is_var || value->IsUndefined(isolate));
     244             : 
     245             :   int index;
     246             :   PropertyAttributes attributes;
     247             :   InitializationFlag init_flag;
     248             :   VariableMode mode;
     249             : 
     250             :   // Check for a conflict with a lexically scoped variable
     251             :   context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, &init_flag,
     252      504173 :                       &mode);
     253      704342 :   if (attributes != ABSENT && IsLexicalVariableMode(mode)) {
     254             :     // ES#sec-evaldeclarationinstantiation 5.a.i.1:
     255             :     // If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
     256             :     // exception.
     257             :     // ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i:
     258             :     // Throw a SyntaxError exception.
     259             :     return ThrowRedeclarationError(isolate, name,
     260         244 :                                    RedeclarationType::kSyntaxError);
     261             :   }
     262             : 
     263             :   Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
     264      503929 :                                           &attributes, &init_flag, &mode);
     265             :   DCHECK(!isolate->has_pending_exception());
     266             : 
     267             :   Handle<JSObject> object;
     268             : 
     269      703840 :   if (attributes != ABSENT && holder->IsJSGlobalObject()) {
     270             :     // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
     271             :     // If fnDefinable is false, throw a TypeError exception.
     272             :     return DeclareGlobal(isolate, Handle<JSGlobalObject>::cast(holder), name,
     273             :                          value, NONE, is_var, is_function,
     274      193181 :                          RedeclarationType::kTypeError);
     275             :   }
     276      310748 :   if (context_arg->extension()->IsJSGlobalObject()) {
     277             :     Handle<JSGlobalObject> global(
     278             :         JSGlobalObject::cast(context_arg->extension()), isolate);
     279             :     return DeclareGlobal(isolate, global, name, value, NONE, is_var,
     280        1479 :                          is_function, RedeclarationType::kTypeError);
     281      309269 :   } else if (context->IsScriptContext()) {
     282             :     DCHECK(context->global_object()->IsJSGlobalObject());
     283             :     Handle<JSGlobalObject> global(
     284          85 :         JSGlobalObject::cast(context->global_object()), isolate);
     285             :     return DeclareGlobal(isolate, global, name, value, NONE, is_var,
     286          85 :                          is_function, RedeclarationType::kTypeError);
     287             :   }
     288             : 
     289      309184 :   if (attributes != ABSENT) {
     290             :     DCHECK_EQ(NONE, attributes);
     291             : 
     292             :     // Skip var re-declarations.
     293        6730 :     if (is_var) return isolate->heap()->undefined_value();
     294             : 
     295             :     DCHECK(is_function);
     296         881 :     if (index != Context::kNotFound) {
     297             :       DCHECK(holder.is_identical_to(context));
     298         164 :       context->set(index, *value);
     299         164 :       return isolate->heap()->undefined_value();
     300             :     }
     301             : 
     302             :     object = Handle<JSObject>::cast(holder);
     303             : 
     304      302454 :   } else if (context->has_extension()) {
     305             :     // Sloppy varblock contexts might not have an extension object yet,
     306             :     // in which case their extension is a ScopeInfo.
     307      269662 :     if (context->extension()->IsScopeInfo()) {
     308             :       DCHECK(context->IsBlockContext());
     309             :       object = isolate->factory()->NewJSObject(
     310        1358 :           isolate->context_extension_function());
     311             :       Handle<HeapObject> extension = isolate->factory()->NewContextExtension(
     312        2716 :           handle(context->scope_info()), object);
     313             :       context->set_extension(*extension);
     314             :     } else {
     315      268304 :       object = handle(context->extension_object(), isolate);
     316             :     }
     317             :     DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
     318             :   } else {
     319             :     // Sloppy eval will never have an extension object, as vars are hoisted out,
     320             :     // and lets are known statically.
     321             :     DCHECK(context->IsFunctionContext());
     322             :     object =
     323       32792 :         isolate->factory()->NewJSObject(isolate->context_extension_function());
     324             :     context->set_extension(*object);
     325             :   }
     326             : 
     327      606342 :   RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
     328             :                                            object, name, value, NONE));
     329             : 
     330      303171 :   return isolate->heap()->undefined_value();
     331             : }
     332             : 
     333             : }  // namespace
     334             : 
     335       31680 : RUNTIME_FUNCTION(Runtime_DeclareEvalFunction) {
     336       15840 :   HandleScope scope(isolate);
     337             :   DCHECK_EQ(2, args.length());
     338       31680 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
     339       15840 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
     340       15840 :   return DeclareEvalHelper(isolate, name, value);
     341             : }
     342             : 
     343      976666 : RUNTIME_FUNCTION(Runtime_DeclareEvalVar) {
     344      488333 :   HandleScope scope(isolate);
     345             :   DCHECK_EQ(1, args.length());
     346      976666 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
     347             :   return DeclareEvalHelper(isolate, name,
     348      976666 :                            isolate->factory()->undefined_value());
     349             : }
     350             : 
     351             : namespace {
     352             : 
     353             : // Find the arguments of the JavaScript function invocation that called
     354             : // into C++ code. Collect these in a newly allocated array of handles.
     355         106 : std::unique_ptr<Handle<Object>[]> GetCallerArguments(Isolate* isolate,
     356             :                                                      int* total_argc) {
     357             :   // Find frame containing arguments passed to the caller.
     358         106 :   JavaScriptFrameIterator it(isolate);
     359             :   JavaScriptFrame* frame = it.frame();
     360             :   List<SharedFunctionInfo*> functions(2);
     361         106 :   frame->GetFunctions(&functions);
     362         106 :   if (functions.length() > 1) {
     363           0 :     int inlined_jsframe_index = functions.length() - 1;
     364           0 :     TranslatedState translated_values(frame);
     365           0 :     translated_values.Prepare(false, frame->fp());
     366             : 
     367           0 :     int argument_count = 0;
     368             :     TranslatedFrame* translated_frame =
     369             :         translated_values.GetArgumentsInfoFromJSFrameIndex(
     370           0 :             inlined_jsframe_index, &argument_count);
     371             :     TranslatedFrame::iterator iter = translated_frame->begin();
     372             : 
     373             :     // Skip the function.
     374             :     iter++;
     375             : 
     376             :     // Skip the receiver.
     377             :     iter++;
     378           0 :     argument_count--;
     379             : 
     380           0 :     *total_argc = argument_count;
     381             :     std::unique_ptr<Handle<Object>[]> param_data(
     382           0 :         NewArray<Handle<Object>>(*total_argc));
     383             :     bool should_deoptimize = false;
     384           0 :     for (int i = 0; i < argument_count; i++) {
     385             :       // If we materialize any object, we should deoptimize the frame because we
     386             :       // might alias an object that was eliminated by escape analysis.
     387           0 :       should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
     388           0 :       Handle<Object> value = iter->GetValue();
     389           0 :       param_data[i] = value;
     390             :       iter++;
     391             :     }
     392             : 
     393           0 :     if (should_deoptimize) {
     394           0 :       translated_values.StoreMaterializedValuesAndDeopt(frame);
     395             :     }
     396             : 
     397             :     return param_data;
     398             :   } else {
     399         106 :     it.AdvanceToArgumentsFrame();
     400             :     frame = it.frame();
     401         106 :     int args_count = frame->ComputeParametersCount();
     402             : 
     403         106 :     *total_argc = args_count;
     404             :     std::unique_ptr<Handle<Object>[]> param_data(
     405         106 :         NewArray<Handle<Object>>(*total_argc));
     406     2654501 :     for (int i = 0; i < args_count; i++) {
     407     2654395 :       Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
     408     5308790 :       param_data[i] = val;
     409             :     }
     410             :     return param_data;
     411             :   }
     412             : }
     413             : 
     414             : template <typename T>
     415         163 : Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
     416             :                                     T parameters, int argument_count) {
     417          91 :   CHECK(!IsDerivedConstructor(callee->shared()->kind()));
     418             :   DCHECK(callee->shared()->has_simple_parameters());
     419             :   Handle<JSObject> result =
     420          91 :       isolate->factory()->NewArgumentsObject(callee, argument_count);
     421             : 
     422             :   // Allocate the elements if needed.
     423             :   int parameter_count = callee->shared()->internal_formal_parameter_count();
     424          91 :   if (argument_count > 0) {
     425          84 :     if (parameter_count > 0) {
     426             :       int mapped_count = Min(argument_count, parameter_count);
     427             :       Handle<FixedArray> parameter_map =
     428          72 :           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
     429         144 :       parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
     430         144 :       result->set_map(isolate->native_context()->fast_aliased_arguments_map());
     431          72 :       result->set_elements(*parameter_map);
     432             : 
     433             :       // Store the context and the arguments array at the beginning of the
     434             :       // parameter map.
     435             :       Handle<Context> context(isolate->context());
     436             :       Handle<FixedArray> arguments =
     437          72 :           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
     438          72 :       parameter_map->set(0, *context);
     439          72 :       parameter_map->set(1, *arguments);
     440             : 
     441             :       // Loop over the actual parameters backwards.
     442          72 :       int index = argument_count - 1;
     443         173 :       while (index >= mapped_count) {
     444             :         // These go directly in the arguments array and have no
     445             :         // corresponding slot in the parameter map.
     446          29 :         arguments->set(index, parameters[index]);
     447          29 :         --index;
     448             :       }
     449             : 
     450             :       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
     451         230 :       while (index >= 0) {
     452             :         // Detect duplicate names to the right in the parameter list.
     453         158 :         Handle<String> name(scope_info->ParameterName(index));
     454         158 :         int context_local_count = scope_info->ContextLocalCount();
     455             :         bool duplicate = false;
     456         165 :         for (int j = index + 1; j < parameter_count; ++j) {
     457         186 :           if (scope_info->ParameterName(j) == *name) {
     458             :             duplicate = true;
     459             :             break;
     460             :           }
     461             :         }
     462             : 
     463         158 :         if (duplicate) {
     464             :           // This goes directly in the arguments array with a hole in the
     465             :           // parameter map.
     466          86 :           arguments->set(index, parameters[index]);
     467         172 :           parameter_map->set_the_hole(index + 2);
     468             :         } else {
     469             :           // The context index goes in the parameter map with a hole in the
     470             :           // arguments array.
     471             :           int context_index = -1;
     472           7 :           for (int j = 0; j < context_local_count; ++j) {
     473         158 :             if (scope_info->ContextLocalName(j) == *name) {
     474             :               context_index = j;
     475             :               break;
     476             :             }
     477             :           }
     478             : 
     479             :           DCHECK(context_index >= 0);
     480          72 :           arguments->set_the_hole(index);
     481             :           parameter_map->set(
     482             :               index + 2,
     483          72 :               Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
     484             :         }
     485             : 
     486         158 :         --index;
     487             :       }
     488             :     } else {
     489             :       // If there is no aliasing, the arguments object elements are not
     490             :       // special in any way.
     491             :       Handle<FixedArray> elements =
     492          12 :           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
     493          12 :       result->set_elements(*elements);
     494      786444 :       for (int i = 0; i < argument_count; ++i) {
     495     1572864 :         elements->set(i, parameters[i]);
     496             :       }
     497             :     }
     498             :   }
     499          91 :   return result;
     500             : }
     501             : 
     502             : 
     503             : class HandleArguments BASE_EMBEDDED {
     504             :  public:
     505          79 :   explicit HandleArguments(Handle<Object>* array) : array_(array) {}
     506         115 :   Object* operator[](int index) { return *array_[index]; }
     507             : 
     508             :  private:
     509             :   Handle<Object>* array_;
     510             : };
     511             : 
     512             : 
     513             : class ParameterArguments BASE_EMBEDDED {
     514             :  public:
     515          12 :   explicit ParameterArguments(Object** parameters) : parameters_(parameters) {}
     516      786432 :   Object*& operator[](int index) { return *(parameters_ - index - 1); }
     517             : 
     518             :  private:
     519             :   Object** parameters_;
     520             : };
     521             : 
     522             : }  // namespace
     523             : 
     524             : 
     525         158 : RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) {
     526          79 :   HandleScope scope(isolate);
     527             :   DCHECK_EQ(1, args.length());
     528         158 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
     529             :   // This generic runtime function can also be used when the caller has been
     530             :   // inlined, we use the slow but accurate {GetCallerArguments}.
     531          79 :   int argument_count = 0;
     532             :   std::unique_ptr<Handle<Object>[]> arguments =
     533         158 :       GetCallerArguments(isolate, &argument_count);
     534          79 :   HandleArguments argument_getter(arguments.get());
     535         237 :   return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
     536             : }
     537             : 
     538             : 
     539          28 : RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
     540          14 :   HandleScope scope(isolate);
     541             :   DCHECK_EQ(1, args.length());
     542          28 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
     543             :   // This generic runtime function can also be used when the caller has been
     544             :   // inlined, we use the slow but accurate {GetCallerArguments}.
     545          14 :   int argument_count = 0;
     546             :   std::unique_ptr<Handle<Object>[]> arguments =
     547          28 :       GetCallerArguments(isolate, &argument_count);
     548             :   Handle<JSObject> result =
     549          14 :       isolate->factory()->NewArgumentsObject(callee, argument_count);
     550          14 :   if (argument_count) {
     551             :     Handle<FixedArray> array =
     552          14 :         isolate->factory()->NewUninitializedFixedArray(argument_count);
     553             :     DisallowHeapAllocation no_gc;
     554          14 :     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
     555     1376256 :     for (int i = 0; i < argument_count; i++) {
     556     2752512 :       array->set(i, *arguments[i], mode);
     557             :     }
     558          14 :     result->set_elements(*array);
     559             :   }
     560          14 :   return *result;
     561             : }
     562             : 
     563             : 
     564          26 : RUNTIME_FUNCTION(Runtime_NewRestParameter) {
     565          13 :   HandleScope scope(isolate);
     566             :   DCHECK_EQ(1, args.length());
     567          26 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
     568          13 :   int start_index = callee->shared()->internal_formal_parameter_count();
     569             :   // This generic runtime function can also be used when the caller has been
     570             :   // inlined, we use the slow but accurate {GetCallerArguments}.
     571          13 :   int argument_count = 0;
     572             :   std::unique_ptr<Handle<Object>[]> arguments =
     573          26 :       GetCallerArguments(isolate, &argument_count);
     574          13 :   int num_elements = std::max(0, argument_count - start_index);
     575             :   Handle<JSObject> result =
     576             :       isolate->factory()->NewJSArray(FAST_ELEMENTS, num_elements, num_elements,
     577          13 :                                      DONT_INITIALIZE_ARRAY_ELEMENTS);
     578             :   {
     579             :     DisallowHeapAllocation no_gc;
     580          13 :     FixedArray* elements = FixedArray::cast(result->elements());
     581          13 :     WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
     582     1277952 :     for (int i = 0; i < num_elements; i++) {
     583     2555904 :       elements->set(i, *arguments[i + start_index], mode);
     584             :     }
     585             :   }
     586          13 :   return *result;
     587             : }
     588             : 
     589             : 
     590          24 : RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
     591          12 :   HandleScope scope(isolate);
     592             :   DCHECK_EQ(1, args.length());
     593          24 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
     594          24 :   StackFrameIterator iterator(isolate);
     595             : 
     596             :   // Stub/interpreter handler frame
     597          12 :   iterator.Advance();
     598             :   DCHECK(iterator.frame()->type() == StackFrame::STUB);
     599             : 
     600             :   // Function frame
     601          12 :   iterator.Advance();
     602          12 :   JavaScriptFrame* function_frame = JavaScriptFrame::cast(iterator.frame());
     603             :   DCHECK(function_frame->is_java_script());
     604          12 :   int argc = function_frame->GetArgumentsLength();
     605          12 :   Address fp = function_frame->fp();
     606          12 :   if (function_frame->has_adapted_arguments()) {
     607          12 :     iterator.Advance();
     608          12 :     fp = iterator.frame()->fp();
     609             :   }
     610             : 
     611             :   Object** parameters = reinterpret_cast<Object**>(
     612          12 :       fp + argc * kPointerSize + StandardFrameConstants::kCallerSPOffset);
     613          12 :   ParameterArguments argument_getter(parameters);
     614          36 :   return *NewSloppyArguments(isolate, callee, argument_getter, argc);
     615             : }
     616             : 
     617           8 : RUNTIME_FUNCTION(Runtime_NewArgumentsElements) {
     618           4 :   HandleScope scope(isolate);
     619             :   DCHECK_EQ(2, args.length());
     620           4 :   Object** frame = reinterpret_cast<Object**>(args[0]);
     621           8 :   CONVERT_SMI_ARG_CHECKED(length, 1);
     622             :   Handle<FixedArray> result =
     623           4 :       isolate->factory()->NewUninitializedFixedArray(length);
     624           4 :   int const offset = length + 1;
     625             :   DisallowHeapAllocation no_gc;
     626           4 :   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
     627      360448 :   for (int index = 0; index < length; ++index) {
     628      720896 :     result->set(index, frame[offset - index], mode);
     629             :   }
     630           4 :   return *result;
     631             : }
     632             : 
     633    10225512 : RUNTIME_FUNCTION(Runtime_NewClosure) {
     634     3408505 :   HandleScope scope(isolate);
     635             :   DCHECK_EQ(3, args.length());
     636     6817010 :   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
     637     6817008 :   CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 1);
     638     6817008 :   CONVERT_SMI_ARG_CHECKED(index, 2);
     639     3408504 :   Handle<Context> context(isolate->context(), isolate);
     640     3408500 :   FeedbackSlot slot = FeedbackVector::ToSlot(index);
     641     3408501 :   Handle<Cell> vector_cell(Cell::cast(vector->Get(slot)), isolate);
     642             :   Handle<JSFunction> function =
     643             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
     644     3408502 :           shared, context, vector_cell, NOT_TENURED);
     645     3408505 :   return *function;
     646             : }
     647             : 
     648             : 
     649    14655408 : RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
     650     4885136 :   HandleScope scope(isolate);
     651             :   DCHECK_EQ(3, args.length());
     652     9770272 :   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
     653     9770272 :   CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 1);
     654     9770272 :   CONVERT_SMI_ARG_CHECKED(index, 2);
     655     4885136 :   Handle<Context> context(isolate->context(), isolate);
     656     4885136 :   FeedbackSlot slot = FeedbackVector::ToSlot(index);
     657     4885136 :   Handle<Cell> vector_cell(Cell::cast(vector->Get(slot)), isolate);
     658             :   // The caller ensures that we pretenure closures that are assigned
     659             :   // directly to properties.
     660             :   Handle<JSFunction> function =
     661             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
     662     4885136 :           shared, context, vector_cell, TENURED);
     663     4885136 :   return *function;
     664             : }
     665             : 
     666       11647 : static Object* FindNameClash(Handle<ScopeInfo> scope_info,
     667             :                              Handle<JSGlobalObject> global_object,
     668             :                              Handle<ScriptContextTable> script_context) {
     669             :   Isolate* isolate = scope_info->GetIsolate();
     670      676240 :   for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
     671      326584 :     Handle<String> name(scope_info->ContextLocalName(var));
     672      326584 :     VariableMode mode = scope_info->ContextLocalMode(var);
     673             :     ScriptContextTable::LookupResult lookup;
     674      326584 :     if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
     675          57 :       if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
     676             :         // ES#sec-globaldeclarationinstantiation 5.b:
     677             :         // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
     678             :         // exception.
     679             :         return ThrowRedeclarationError(isolate, name,
     680         168 :                                        RedeclarationType::kSyntaxError);
     681             :       }
     682             :     }
     683             : 
     684      326527 :     if (IsLexicalVariableMode(mode)) {
     685             :       LookupIterator it(global_object, name, global_object,
     686      326527 :                         LookupIterator::OWN_SKIP_INTERCEPTOR);
     687      326527 :       Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
     688      326581 :       if (!maybe.IsJust()) return isolate->heap()->exception();
     689      326527 :       if ((maybe.FromJust() & DONT_DELETE) != 0) {
     690             :         // ES#sec-globaldeclarationinstantiation 5.a:
     691             :         // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError
     692             :         // exception.
     693             :         // ES#sec-globaldeclarationinstantiation 5.d:
     694             :         // If hasRestrictedGlobal is true, throw a SyntaxError exception.
     695             :         return ThrowRedeclarationError(isolate, name,
     696          54 :                                        RedeclarationType::kSyntaxError);
     697             :       }
     698             : 
     699      326473 :       JSGlobalObject::InvalidatePropertyCell(global_object, name);
     700             :     }
     701             :   }
     702       11536 :   return isolate->heap()->undefined_value();
     703             : }
     704             : 
     705             : 
     706       23294 : RUNTIME_FUNCTION(Runtime_NewScriptContext) {
     707       11647 :   HandleScope scope(isolate);
     708             :   DCHECK_EQ(2, args.length());
     709             : 
     710       23294 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     711       23294 :   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
     712       11647 :   Handle<JSGlobalObject> global_object(function->context()->global_object());
     713       11647 :   Handle<Context> native_context(global_object->native_context());
     714             :   Handle<ScriptContextTable> script_context_table(
     715       11647 :       native_context->script_context_table());
     716             : 
     717             :   Object* name_clash_result =
     718       11647 :       FindNameClash(scope_info, global_object, script_context_table);
     719       11647 :   if (isolate->has_pending_exception()) return name_clash_result;
     720             : 
     721             :   // Script contexts have a canonical empty function as their closure, not the
     722             :   // anonymous closure containing the global code.  See
     723             :   // FullCodeGenerator::PushFunctionArgumentForContextAllocation.
     724       11536 :   Handle<JSFunction> closure(function->shared()->IsUserJavaScript()
     725             :                                  ? native_context->closure()
     726       23072 :                                  : *function);
     727             :   Handle<Context> result =
     728       11536 :       isolate->factory()->NewScriptContext(closure, scope_info);
     729             : 
     730             :   DCHECK(function->context() == isolate->context());
     731             :   DCHECK(*global_object == result->global_object());
     732             : 
     733             :   Handle<ScriptContextTable> new_script_context_table =
     734       11536 :       ScriptContextTable::Extend(script_context_table, result);
     735       11536 :   native_context->set_script_context_table(*new_script_context_table);
     736       11647 :   return *result;
     737             : }
     738             : 
     739          30 : RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
     740          15 :   HandleScope scope(isolate);
     741             :   DCHECK_EQ(2, args.length());
     742             : 
     743          30 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     744          30 :   CONVERT_SMI_ARG_CHECKED(scope_type, 1);
     745             : 
     746             :   DCHECK(function->context() == isolate->context());
     747          15 :   int length = function->shared()->scope_info()->ContextLength();
     748             :   return *isolate->factory()->NewFunctionContext(
     749          30 :       length, function, static_cast<ScopeType>(scope_type));
     750             : }
     751             : 
     752      882039 : RUNTIME_FUNCTION(Runtime_PushWithContext) {
     753      294013 :   HandleScope scope(isolate);
     754             :   DCHECK_EQ(3, args.length());
     755      588026 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0);
     756      588026 :   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
     757      588026 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
     758      294013 :   Handle<Context> current(isolate->context());
     759             :   Handle<Context> context = isolate->factory()->NewWithContext(
     760      294013 :       function, current, scope_info, extension_object);
     761      294013 :   isolate->set_context(*context);
     762      294013 :   return *context;
     763             : }
     764             : 
     765        3750 : RUNTIME_FUNCTION(Runtime_PushModuleContext) {
     766        1875 :   HandleScope scope(isolate);
     767             :   DCHECK_EQ(3, args.length());
     768        3750 :   CONVERT_ARG_HANDLE_CHECKED(Module, module, 0);
     769        3750 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
     770        3750 :   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 2);
     771             :   DCHECK(function->context() == isolate->context());
     772             : 
     773             :   Handle<Context> context =
     774        1875 :       isolate->factory()->NewModuleContext(module, function, scope_info);
     775        1875 :   isolate->set_context(*context);
     776        1875 :   return *context;
     777             : }
     778             : 
     779     2722320 : RUNTIME_FUNCTION(Runtime_PushCatchContext) {
     780      907440 :   HandleScope scope(isolate);
     781             :   DCHECK_EQ(4, args.length());
     782     1814880 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
     783      907440 :   CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
     784     1814880 :   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 2);
     785     1814880 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 3);
     786      907440 :   Handle<Context> current(isolate->context());
     787             :   Handle<Context> context = isolate->factory()->NewCatchContext(
     788      907440 :       function, current, scope_info, name, thrown_object);
     789      907440 :   isolate->set_context(*context);
     790      907440 :   return *context;
     791             : }
     792             : 
     793             : 
     794      252216 : RUNTIME_FUNCTION(Runtime_PushBlockContext) {
     795       84072 :   HandleScope scope(isolate);
     796             :   DCHECK_EQ(2, args.length());
     797      168144 :   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
     798      168144 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
     799       84072 :   Handle<Context> current(isolate->context());
     800             :   Handle<Context> context =
     801       84072 :       isolate->factory()->NewBlockContext(function, current, scope_info);
     802       84072 :   isolate->set_context(*context);
     803       84072 :   return *context;
     804             : }
     805             : 
     806             : 
     807        1224 : RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
     808         408 :   HandleScope scope(isolate);
     809             :   DCHECK_EQ(1, args.length());
     810         816 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
     811             : 
     812             :   int index;
     813             :   PropertyAttributes attributes;
     814             :   InitializationFlag flag;
     815             :   VariableMode mode;
     816             :   Handle<Object> holder = isolate->context()->Lookup(
     817         408 :       name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode);
     818             : 
     819             :   // If the slot was not found the result is true.
     820         408 :   if (holder.is_null()) {
     821             :     // In case of JSProxy, an exception might have been thrown.
     822          66 :     if (isolate->has_pending_exception()) return isolate->heap()->exception();
     823          66 :     return isolate->heap()->true_value();
     824             :   }
     825             : 
     826             :   // If the slot was found in a context, it should be DONT_DELETE.
     827         342 :   if (holder->IsContext()) {
     828          90 :     return isolate->heap()->false_value();
     829             :   }
     830             : 
     831             :   // The slot was found in a JSReceiver, either a context extension object,
     832             :   // the global object, or the subject of a with.  Try to delete it
     833             :   // (respecting DONT_DELETE).
     834         252 :   Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
     835         252 :   Maybe<bool> result = JSReceiver::DeleteProperty(object, name);
     836         252 :   MAYBE_RETURN(result, isolate->heap()->exception());
     837         252 :   return isolate->heap()->ToBoolean(result.FromJust());
     838             : }
     839             : 
     840             : 
     841             : namespace {
     842             : 
     843     1971417 : MaybeHandle<Object> LoadLookupSlot(Handle<String> name,
     844             :                                    Object::ShouldThrow should_throw,
     845             :                                    Handle<Object>* receiver_return = nullptr) {
     846     1971417 :   Isolate* const isolate = name->GetIsolate();
     847             : 
     848             :   int index;
     849             :   PropertyAttributes attributes;
     850             :   InitializationFlag flag;
     851             :   VariableMode mode;
     852             :   Handle<Object> holder = isolate->context()->Lookup(
     853     1971417 :       name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode);
     854     1971417 :   if (isolate->has_pending_exception()) return MaybeHandle<Object>();
     855             : 
     856     1971368 :   if (index != Context::kNotFound) {
     857             :     DCHECK(holder->IsContext());
     858             :     // If the "property" we were looking for is a local variable, the
     859             :     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
     860             :     Handle<Object> receiver = isolate->factory()->undefined_value();
     861             :     Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate);
     862             :     // Check for uninitialized bindings.
     863      506647 :     if (flag == kNeedsInitialization && value->IsTheHole(isolate)) {
     864        1682 :       THROW_NEW_ERROR(isolate,
     865             :                       NewReferenceError(MessageTemplate::kNotDefined, name),
     866             :                       Object);
     867             :     }
     868             :     DCHECK(!value->IsTheHole(isolate));
     869      469898 :     if (receiver_return) *receiver_return = receiver;
     870             :     return value;
     871             :   }
     872             : 
     873             :   // Otherwise, if the slot was found the holder is a context extension
     874             :   // object, subject of a with, or a global object.  We read the named
     875             :   // property from it.
     876     1500629 :   if (!holder.is_null()) {
     877             :     // No need to unhole the value here.  This is taken care of by the
     878             :     // GetProperty function.
     879             :     Handle<Object> value;
     880     2999954 :     ASSIGN_RETURN_ON_EXCEPTION(
     881             :         isolate, value, Object::GetProperty(holder, name),
     882             :         Object);
     883     1499932 :     if (receiver_return) {
     884             :       *receiver_return =
     885       18822 :           (holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject())
     886             :               ? Handle<Object>::cast(isolate->factory()->undefined_value())
     887      551882 :               : holder;
     888             :     }
     889             :     return value;
     890             :   }
     891             : 
     892         652 :   if (should_throw == Object::THROW_ON_ERROR) {
     893             :     // The property doesn't exist - throw exception.
     894        1138 :     THROW_NEW_ERROR(
     895             :         isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
     896             :   }
     897             : 
     898             :   // The property doesn't exist - return undefined.
     899          83 :   if (receiver_return) *receiver_return = isolate->factory()->undefined_value();
     900             :   return isolate->factory()->undefined_value();
     901             : }
     902             : 
     903             : }  // namespace
     904             : 
     905             : 
     906     3370038 : RUNTIME_FUNCTION(Runtime_LoadLookupSlot) {
     907     1685019 :   HandleScope scope(isolate);
     908             :   DCHECK_EQ(1, args.length());
     909     3370038 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
     910     3370038 :   RETURN_RESULT_OR_FAILURE(isolate,
     911     1685019 :                            LoadLookupSlot(name, Object::THROW_ON_ERROR));
     912             : }
     913             : 
     914             : 
     915        1298 : RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof) {
     916         649 :   HandleScope scope(isolate);
     917             :   DCHECK_EQ(1, args.length());
     918        1298 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
     919        1947 :   RETURN_RESULT_OR_FAILURE(isolate, LoadLookupSlot(name, Object::DONT_THROW));
     920             : }
     921             : 
     922             : 
     923      285749 : RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotForCall) {
     924      285749 :   HandleScope scope(isolate);
     925             :   DCHECK_EQ(1, args.length());
     926             :   DCHECK(args[0]->IsString());
     927      285749 :   Handle<String> name = args.at<String>(0);
     928             :   Handle<Object> value;
     929             :   Handle<Object> receiver;
     930      571498 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     931             :       isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR, &receiver),
     932             :       MakePair(isolate->heap()->exception(), nullptr));
     933      285719 :   return MakePair(*value, *receiver);
     934             : }
     935             : 
     936             : 
     937             : namespace {
     938             : 
     939     3481439 : MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value,
     940             :                                     LanguageMode language_mode) {
     941     3481439 :   Isolate* const isolate = name->GetIsolate();
     942             :   Handle<Context> context(isolate->context(), isolate);
     943             : 
     944             :   int index;
     945             :   PropertyAttributes attributes;
     946             :   InitializationFlag flag;
     947             :   VariableMode mode;
     948             :   Handle<Object> holder =
     949     3481439 :       context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode);
     950     3481439 :   if (holder.is_null()) {
     951             :     // In case of JSProxy, an exception might have been thrown.
     952         747 :     if (isolate->has_pending_exception()) return MaybeHandle<Object>();
     953             :   }
     954             : 
     955             :   // The property was found in a context slot.
     956     3481376 :   if (index != Context::kNotFound) {
     957     2342994 :     if (flag == kNeedsInitialization &&
     958         253 :         Handle<Context>::cast(holder)->is_the_hole(isolate, index)) {
     959         168 :       THROW_NEW_ERROR(isolate,
     960             :                       NewReferenceError(MessageTemplate::kNotDefined, name),
     961             :                       Object);
     962             :     }
     963     2342657 :     if ((attributes & READ_ONLY) == 0) {
     964     4685136 :       Handle<Context>::cast(holder)->set(index, *value);
     965          89 :     } else if (is_strict(language_mode)) {
     966             :       // Setting read only property in strict mode.
     967          30 :       THROW_NEW_ERROR(isolate,
     968             :                       NewTypeError(MessageTemplate::kStrictCannotAssign, name),
     969             :                       Object);
     970             :     }
     971             :     return value;
     972             :   }
     973             : 
     974             :   // Slow case: The property is not in a context slot.  It is either in a
     975             :   // context extension object, a property of the subject of a with, or a
     976             :   // property of the global object.
     977             :   Handle<JSReceiver> object;
     978     1138635 :   if (attributes != ABSENT) {
     979             :     // The property exists on the holder.
     980             :     object = Handle<JSReceiver>::cast(holder);
     981         684 :   } else if (is_strict(language_mode)) {
     982             :     // If absent in strict mode: throw.
     983          84 :     THROW_NEW_ERROR(
     984             :         isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
     985             :   } else {
     986             :     // If absent in sloppy mode: add the property to the global object.
     987         642 :     object = Handle<JSReceiver>(context->global_object());
     988             :   }
     989             : 
     990     2277186 :   ASSIGN_RETURN_ON_EXCEPTION(
     991             :       isolate, value, Object::SetProperty(object, name, value, language_mode),
     992             :       Object);
     993             :   return value;
     994             : }
     995             : 
     996             : }  // namespace
     997             : 
     998             : 
     999     6955368 : RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Sloppy) {
    1000     3477684 :   HandleScope scope(isolate);
    1001             :   DCHECK_EQ(2, args.length());
    1002     6955368 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
    1003     3477684 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
    1004    10433052 :   RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, SLOPPY));
    1005             : }
    1006             : 
    1007             : 
    1008        7510 : RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) {
    1009        3755 :   HandleScope scope(isolate);
    1010             :   DCHECK_EQ(2, args.length());
    1011        7510 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
    1012        3755 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
    1013       11265 :   RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT));
    1014             : }
    1015             : 
    1016             : }  // namespace internal
    1017             : }  // namespace v8

Generated by: LCOV version 1.10