Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc
index 2a0b435..094f1a1 100644
--- a/src/runtime/runtime-scopes.cc
+++ b/src/runtime/runtime-scopes.cc
@@ -2,36 +2,36 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
+#include "src/runtime/runtime-utils.h"
#include "src/accessors.h"
#include "src/arguments.h"
+#include "src/ast/scopeinfo.h"
+#include "src/ast/scopes.h"
+#include "src/deoptimizer.h"
#include "src/frames-inl.h"
-#include "src/runtime/runtime-utils.h"
-#include "src/scopeinfo.h"
-#include "src/scopes.h"
+#include "src/isolate-inl.h"
+#include "src/messages.h"
namespace v8 {
namespace internal {
static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
HandleScope scope(isolate);
- Handle<Object> args[1] = {name};
THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewTypeError("var_redeclaration", HandleVector(args, 1)));
+ isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
}
RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) {
HandleScope scope(isolate);
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate,
- NewTypeError("harmony_const_assign", HandleVector<Object>(NULL, 0)));
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate,
+ NewTypeError(MessageTemplate::kConstAssign));
}
// May throw a RedeclarationError.
-static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> global,
+static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global,
Handle<String> name, Handle<Object> value,
PropertyAttributes attr, bool is_var,
bool is_const, bool is_function) {
@@ -46,10 +46,10 @@
// Do the lookup own properties only, see ES5 erratum.
LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
- if (!maybe.has_value) return isolate->heap()->exception();
+ if (!maybe.IsJust()) return isolate->heap()->exception();
if (it.IsFound()) {
- PropertyAttributes old_attributes = maybe.value;
+ PropertyAttributes old_attributes = maybe.FromJust();
// The name was declared before; check for conflicting re-declarations.
if (is_const) return ThrowRedeclarationError(isolate, name);
@@ -65,10 +65,11 @@
// Check whether we can reconfigure the existing property into a
// function.
PropertyDetails old_details = it.property_details();
- // TODO(verwaest): CALLBACKS invalidly includes ExecutableAccessInfo,
+ // TODO(verwaest): ACCESSOR_CONSTANT invalidly includes
+ // ExecutableAccessInfo,
// which are actually data properties, not accessor properties.
if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
- old_details.type() == CALLBACKS) {
+ old_details.type() == ACCESSOR_CONSTANT) {
return ThrowRedeclarationError(isolate, name);
}
// If the existing property is not configurable, keep its attributes. Do
@@ -86,12 +87,12 @@
RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
HandleScope scope(isolate);
- DCHECK(args.length() == 3);
- Handle<GlobalObject> global(isolate->global_object());
+ DCHECK_EQ(2, args.length());
+ Handle<JSGlobalObject> global(isolate->global_object());
+ Handle<Context> context(isolate->context());
- CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
- CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
- CONVERT_SMI_ARG_CHECKED(flags, 2);
+ CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0);
+ CONVERT_SMI_ARG_CHECKED(flags, 1);
// Traverse the name/value pairs and set the properties.
int length = pairs->length();
@@ -106,7 +107,8 @@
bool is_var = initial_value->IsUndefined();
bool is_const = initial_value->IsTheHole();
bool is_function = initial_value->IsSharedFunctionInfo();
- DCHECK(is_var + is_const + is_function == 1);
+ DCHECK_EQ(1,
+ BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
Handle<Object> value;
if (is_function) {
@@ -151,13 +153,13 @@
RUNTIME_ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
- CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
+ CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
- Handle<GlobalObject> global(isolate->context()->global_object());
+ Handle<JSGlobalObject> global(isolate->context()->global_object());
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, Object::SetProperty(global, name, value, strict_mode));
+ isolate, result, Object::SetProperty(global, name, value, language_mode));
return *result;
}
@@ -171,13 +173,13 @@
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
- Handle<GlobalObject> global = isolate->global_object();
+ Handle<JSGlobalObject> global = isolate->global_object();
// Lookup the property as own on the global object.
LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
- DCHECK(maybe.has_value);
- PropertyAttributes old_attributes = maybe.value;
+ DCHECK(maybe.IsJust());
+ PropertyAttributes old_attributes = maybe.FromJust();
PropertyAttributes attr =
static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
@@ -201,33 +203,48 @@
}
-RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 4);
+namespace {
- // Declarations are always made in a function, eval or script context. In
- // the case of eval code, the context passed is the context of the caller,
+Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name,
+ Handle<Object> initial_value,
+ PropertyAttributes attr) {
+ // Declarations are always made in a function, eval or script context, or
+ // a declaration block scope.
+ // In the case of eval code, the context passed is the context of the caller,
// which may be some nested context and not the declaration context.
- CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 0);
- Handle<Context> context(context_arg->declaration_context());
- CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
- CONVERT_SMI_ARG_CHECKED(attr_arg, 2);
- PropertyAttributes attr = static_cast<PropertyAttributes>(attr_arg);
- RUNTIME_ASSERT(attr == READ_ONLY || attr == NONE);
- CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3);
+ Handle<Context> context_arg(isolate->context(), isolate);
+ Handle<Context> context(context_arg->declaration_context(), isolate);
// TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
bool is_var = *initial_value == NULL;
bool is_const = initial_value->IsTheHole();
bool is_function = initial_value->IsJSFunction();
- DCHECK(is_var + is_const + is_function == 1);
+ DCHECK_EQ(1,
+ BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
int index;
PropertyAttributes attributes;
- ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
BindingFlags binding_flags;
- Handle<Object> holder =
- context->Lookup(name, flags, &index, &attributes, &binding_flags);
+
+ if ((attr & EVAL_DECLARED) != 0) {
+ // Check for a conflict with a lexically scoped variable
+ context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes,
+ &binding_flags);
+ if (attributes != ABSENT &&
+ (binding_flags == MUTABLE_CHECK_INITIALIZED ||
+ binding_flags == IMMUTABLE_CHECK_INITIALIZED ||
+ binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY)) {
+ return ThrowRedeclarationError(isolate, name);
+ }
+ attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED);
+ }
+
+ Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
+ &attributes, &binding_flags);
+ if (holder.is_null()) {
+ // In case of JSProxy, an exception might have been thrown.
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
+ }
Handle<JSObject> object;
Handle<Object> value =
@@ -236,12 +253,22 @@
// TODO(verwaest): This case should probably not be covered by this function,
// but by DeclareGlobals instead.
- if ((attributes != ABSENT && holder->IsJSGlobalObject()) ||
- (context_arg->has_extension() &&
- context_arg->extension()->IsJSGlobalObject())) {
+ if (attributes != ABSENT && holder->IsJSGlobalObject()) {
return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
value, attr, is_var, is_const, is_function);
}
+ if (context_arg->extension()->IsJSGlobalObject()) {
+ Handle<JSGlobalObject> global(
+ JSGlobalObject::cast(context_arg->extension()), isolate);
+ return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
+ is_function);
+ } else if (context->IsScriptContext()) {
+ DCHECK(context->global_object()->IsJSGlobalObject());
+ Handle<JSGlobalObject> global(
+ JSGlobalObject::cast(context->global_object()), isolate);
+ return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
+ is_function);
+ }
if (attributes != ABSENT) {
// The name was declared before; check for conflicting re-declarations.
@@ -253,7 +280,7 @@
if (is_var) return isolate->heap()->undefined_value();
DCHECK(is_function);
- if (index >= 0) {
+ if (index != Context::kNotFound) {
DCHECK(holder.is_identical_to(context));
context->set(index, *initial_value);
return isolate->heap()->undefined_value();
@@ -262,7 +289,19 @@
object = Handle<JSObject>::cast(holder);
} else if (context->has_extension()) {
- object = handle(JSObject::cast(context->extension()));
+ // Sloppy varblock contexts might not have an extension object yet,
+ // in which case their extension is a ScopeInfo.
+ if (context->extension()->IsScopeInfo()) {
+ DCHECK(context->IsBlockContext());
+ object = isolate->factory()->NewJSObject(
+ isolate->context_extension_function());
+ Handle<HeapObject> extension =
+ isolate->factory()->NewSloppyBlockWithEvalContextExtension(
+ handle(context->scope_info()), object);
+ context->set_extension(*extension);
+ } else {
+ object = handle(context->extension_object(), isolate);
+ }
DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
} else {
DCHECK(context->IsFunctionContext());
@@ -277,6 +316,21 @@
return isolate->heap()->undefined_value();
}
+} // namespace
+
+
+RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(3, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Smi, property_attributes, 2);
+
+ PropertyAttributes attributes =
+ static_cast<PropertyAttributes>(property_attributes->value());
+ return DeclareLookupSlot(isolate, name, initial_value, attributes);
+}
+
RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
HandleScope scope(isolate);
@@ -295,8 +349,12 @@
BindingFlags binding_flags;
Handle<Object> holder =
context->Lookup(name, flags, &index, &attributes, &binding_flags);
+ if (holder.is_null()) {
+ // In case of JSProxy, an exception might have been thrown.
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
+ }
- if (index >= 0) {
+ if (index != Context::kNotFound) {
DCHECK(holder->IsContext());
// Property was found in a context. Perform the assignment if the constant
// was uninitialized.
@@ -316,8 +374,12 @@
// meanwhile. If so, re-introduce the variable in the context extension.
if (attributes == ABSENT) {
Handle<Context> declaration_context(context_arg->declaration_context());
- DCHECK(declaration_context->has_extension());
- holder = handle(declaration_context->extension(), isolate);
+ if (declaration_context->IsScriptContext()) {
+ holder = handle(declaration_context->global_object(), isolate);
+ } else {
+ holder = handle(declaration_context->extension_object(), isolate);
+ DCHECK(!holder.is_null());
+ }
CHECK(holder->IsJSObject());
} else {
// For JSContextExtensionObjects, the initializer can be run multiple times
@@ -328,8 +390,8 @@
LookupIterator it(holder, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
- if (!maybe.has_value) return isolate->heap()->exception();
- PropertyAttributes old_attributes = maybe.value;
+ if (!maybe.IsJust()) return isolate->heap()->exception();
+ PropertyAttributes old_attributes = maybe.FromJust();
// Ignore if we can't reconfigure the value.
if ((old_attributes & DONT_DELETE) != 0) {
@@ -349,26 +411,87 @@
}
-static Handle<JSObject> NewSloppyArguments(Isolate* isolate,
- Handle<JSFunction> callee,
- Object** parameters,
- int argument_count) {
+namespace {
+
+// Find the arguments of the JavaScript function invocation that called
+// into C++ code. Collect these in a newly allocated array of handles (possibly
+// prefixed by a number of empty handles).
+base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate,
+ int prefix_argc,
+ int* total_argc) {
+ // Find frame containing arguments passed to the caller.
+ JavaScriptFrameIterator it(isolate);
+ JavaScriptFrame* frame = it.frame();
+ List<JSFunction*> functions(2);
+ frame->GetFunctions(&functions);
+ if (functions.length() > 1) {
+ int inlined_jsframe_index = functions.length() - 1;
+ TranslatedState translated_values(frame);
+ translated_values.Prepare(false, frame->fp());
+
+ int argument_count = 0;
+ TranslatedFrame* translated_frame =
+ translated_values.GetArgumentsInfoFromJSFrameIndex(
+ inlined_jsframe_index, &argument_count);
+ TranslatedFrame::iterator iter = translated_frame->begin();
+
+ // Skip the function.
+ iter++;
+
+ // Skip the receiver.
+ iter++;
+ argument_count--;
+
+ *total_argc = prefix_argc + argument_count;
+ base::SmartArrayPointer<Handle<Object>> param_data(
+ NewArray<Handle<Object>>(*total_argc));
+ bool should_deoptimize = false;
+ for (int i = 0; i < argument_count; i++) {
+ should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
+ Handle<Object> value = iter->GetValue();
+ param_data[prefix_argc + i] = value;
+ iter++;
+ }
+
+ if (should_deoptimize) {
+ translated_values.StoreMaterializedValuesAndDeopt();
+ }
+
+ return param_data;
+ } else {
+ it.AdvanceToArgumentsFrame();
+ frame = it.frame();
+ int args_count = frame->ComputeParametersCount();
+
+ *total_argc = prefix_argc + args_count;
+ base::SmartArrayPointer<Handle<Object>> param_data(
+ NewArray<Handle<Object>>(*total_argc));
+ for (int i = 0; i < args_count; i++) {
+ Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
+ param_data[prefix_argc + i] = val;
+ }
+ return param_data;
+ }
+}
+
+
+template <typename T>
+Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
+ T parameters, int argument_count) {
+ CHECK(!IsSubclassConstructor(callee->shared()->kind()));
+ DCHECK(callee->shared()->has_simple_parameters());
Handle<JSObject> result =
isolate->factory()->NewArgumentsObject(callee, argument_count);
// Allocate the elements if needed.
- int parameter_count = callee->shared()->formal_parameter_count();
+ int parameter_count = callee->shared()->internal_formal_parameter_count();
if (argument_count > 0) {
if (parameter_count > 0) {
int mapped_count = Min(argument_count, parameter_count);
Handle<FixedArray> parameter_map =
isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
-
- Handle<Map> map = Map::Copy(handle(result->map()), "NewSloppyArguments");
- map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
-
- result->set_map(*map);
+ result->set_map(isolate->native_context()->fast_aliased_arguments_map());
result->set_elements(*parameter_map);
// Store the context and the arguments array at the beginning of the
@@ -384,7 +507,7 @@
while (index >= mapped_count) {
// These go directly in the arguments array and have no
// corresponding slot in the parameter map.
- arguments->set(index, *(parameters - index - 1));
+ arguments->set(index, parameters[index]);
--index;
}
@@ -404,7 +527,7 @@
if (duplicate) {
// This goes directly in the arguments array with a hole in the
// parameter map.
- arguments->set(index, *(parameters - index - 1));
+ arguments->set(index, parameters[index]);
parameter_map->set_the_hole(index + 2);
} else {
// The context index goes in the parameter map with a hole in the
@@ -416,6 +539,7 @@
break;
}
}
+
DCHECK(context_index >= 0);
arguments->set_the_hole(index);
parameter_map->set(
@@ -432,7 +556,7 @@
isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
result->set_elements(*elements);
for (int i = 0; i < argument_count; ++i) {
- elements->set(i, *(parameters - i - 1));
+ elements->set(i, parameters[i]);
}
}
}
@@ -440,10 +564,9 @@
}
-static Handle<JSObject> NewStrictArguments(Isolate* isolate,
- Handle<JSFunction> callee,
- Object** parameters,
- int argument_count) {
+template <typename T>
+Handle<JSObject> NewStrictArguments(Isolate* isolate, Handle<JSFunction> callee,
+ T parameters, int argument_count) {
Handle<JSObject> result =
isolate->factory()->NewArgumentsObject(callee, argument_count);
@@ -453,7 +576,7 @@
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < argument_count; i++) {
- array->set(i, *--parameters, mode);
+ array->set(i, parameters[i], mode);
}
result->set_elements(*array);
}
@@ -461,22 +584,89 @@
}
-RUNTIME_FUNCTION(Runtime_NewArguments) {
+template <typename T>
+Handle<JSObject> NewRestArguments(Isolate* isolate, Handle<JSFunction> callee,
+ T parameters, int argument_count,
+ int start_index) {
+ int num_elements = std::max(0, argument_count - start_index);
+ Handle<JSObject> result = isolate->factory()->NewJSArray(
+ FAST_ELEMENTS, num_elements, num_elements, Strength::WEAK,
+ DONT_INITIALIZE_ARRAY_ELEMENTS);
+ {
+ DisallowHeapAllocation no_gc;
+ FixedArray* elements = FixedArray::cast(result->elements());
+ WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
+ for (int i = 0; i < num_elements; i++) {
+ elements->set(i, parameters[i + start_index], mode);
+ }
+ }
+ return result;
+}
+
+
+class HandleArguments BASE_EMBEDDED {
+ public:
+ explicit HandleArguments(Handle<Object>* array) : array_(array) {}
+ Object* operator[](int index) { return *array_[index]; }
+
+ private:
+ Handle<Object>* array_;
+};
+
+
+class ParameterArguments BASE_EMBEDDED {
+ public:
+ explicit ParameterArguments(Object** parameters) : parameters_(parameters) {}
+ Object*& operator[](int index) { return *(parameters_ - index - 1); }
+
+ private:
+ Object** parameters_;
+};
+
+} // namespace
+
+
+RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
- JavaScriptFrameIterator it(isolate);
+ // This generic runtime function can also be used when the caller has been
+ // inlined, we use the slow but accurate {GetCallerArguments}.
+ int argument_count = 0;
+ base::SmartArrayPointer<Handle<Object>> arguments =
+ GetCallerArguments(isolate, 0, &argument_count);
+ HandleArguments argument_getter(arguments.get());
+ return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
+}
- // Find the frame that holds the actual arguments passed to the function.
- it.AdvanceToArgumentsFrame();
- JavaScriptFrame* frame = it.frame();
- // Determine parameter location on the stack and dispatch on language mode.
- int argument_count = frame->GetArgumentsLength();
- Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1));
- return callee->shared()->strict_mode() == STRICT
- ? *NewStrictArguments(isolate, callee, parameters, argument_count)
- : *NewSloppyArguments(isolate, callee, parameters, argument_count);
+RUNTIME_FUNCTION(Runtime_NewStrictArguments_Generic) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
+ // This generic runtime function can also be used when the caller has been
+ // inlined, we use the slow but accurate {GetCallerArguments}.
+ int argument_count = 0;
+ base::SmartArrayPointer<Handle<Object>> arguments =
+ GetCallerArguments(isolate, 0, &argument_count);
+ HandleArguments argument_getter(arguments.get());
+ return *NewStrictArguments(isolate, callee, argument_getter, argument_count);
+}
+
+
+RUNTIME_FUNCTION(Runtime_NewRestArguments_Generic) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
+ CONVERT_SMI_ARG_CHECKED(start_index, 1);
+ // This generic runtime function can also be used when the caller has been
+ // inlined, we use the slow but accurate {GetCallerArguments}.
+ int argument_count = 0;
+ base::SmartArrayPointer<Handle<Object>> arguments =
+ GetCallerArguments(isolate, 0, &argument_count);
+ HandleArguments argument_getter(arguments.get());
+ return *NewRestArguments(isolate, callee, argument_getter, argument_count,
+ start_index);
}
@@ -486,7 +676,14 @@
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
Object** parameters = reinterpret_cast<Object**>(args[1]);
CONVERT_SMI_ARG_CHECKED(argument_count, 2);
- return *NewSloppyArguments(isolate, callee, parameters, argument_count);
+#ifdef DEBUG
+ // This runtime function does not materialize the correct arguments when the
+ // caller has been inlined, better make sure we are not hitting that case.
+ JavaScriptFrameIterator it(isolate);
+ DCHECK(!it.frame()->HasInlinedFrames());
+#endif // DEBUG
+ ParameterArguments argument_getter(parameters);
+ return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
}
@@ -496,37 +693,59 @@
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
Object** parameters = reinterpret_cast<Object**>(args[1]);
CONVERT_SMI_ARG_CHECKED(argument_count, 2);
- return *NewStrictArguments(isolate, callee, parameters, argument_count);
+#ifdef DEBUG
+ // This runtime function does not materialize the correct arguments when the
+ // caller has been inlined, better make sure we are not hitting that case.
+ JavaScriptFrameIterator it(isolate);
+ DCHECK(!it.frame()->HasInlinedFrames());
+#endif // DEBUG
+ ParameterArguments argument_getter(parameters);
+ return *NewStrictArguments(isolate, callee, argument_getter, argument_count);
}
-RUNTIME_FUNCTION(Runtime_NewClosureFromStubFailure) {
+RUNTIME_FUNCTION(Runtime_NewRestParam) {
HandleScope scope(isolate);
- DCHECK(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
- Handle<Context> context(isolate->context());
- PretenureFlag pretenure_flag = NOT_TENURED;
- return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
- pretenure_flag);
+ DCHECK(args.length() == 3);
+ CONVERT_SMI_ARG_CHECKED(num_params, 0);
+ Object** parameters = reinterpret_cast<Object**>(args[1]);
+ CONVERT_SMI_ARG_CHECKED(rest_index, 2);
+#ifdef DEBUG
+ // This runtime function does not materialize the correct arguments when the
+ // caller has been inlined, better make sure we are not hitting that case.
+ JavaScriptFrameIterator it(isolate);
+ DCHECK(!it.frame()->HasInlinedFrames());
+#endif // DEBUG
+ Handle<JSFunction> callee;
+ ParameterArguments argument_getter(parameters);
+ return *NewRestArguments(isolate, callee, argument_getter, num_params,
+ rest_index);
}
RUNTIME_FUNCTION(Runtime_NewClosure) {
HandleScope scope(isolate);
- DCHECK(args.length() == 3);
- CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
- CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
- CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
+ Handle<Context> context(isolate->context(), isolate);
+ return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
+ NOT_TENURED);
+}
+
+RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
+ Handle<Context> context(isolate->context(), isolate);
// The caller ensures that we pretenure closures that are assigned
// directly to properties.
- PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
- pretenure_flag);
+ TENURED);
}
static Object* FindNameClash(Handle<ScopeInfo> scope_info,
- Handle<GlobalObject> global_object,
+ Handle<JSGlobalObject> global_object,
Handle<ScriptContextTable> script_context) {
Isolate* isolate = scope_info->GetIsolate();
for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
@@ -543,12 +762,12 @@
LookupIterator it(global_object, name,
LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
- if (!maybe.has_value) return isolate->heap()->exception();
- if ((maybe.value & DONT_DELETE) != 0) {
+ if (!maybe.IsJust()) return isolate->heap()->exception();
+ if ((maybe.FromJust() & DONT_DELETE) != 0) {
return ThrowRedeclarationError(isolate, name);
}
- GlobalObject::InvalidatePropertyCell(global_object, name);
+ JSGlobalObject::InvalidatePropertyCell(global_object, name);
}
}
return isolate->heap()->undefined_value();
@@ -561,21 +780,27 @@
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
- Handle<GlobalObject> global_object(function->context()->global_object());
+ Handle<JSGlobalObject> global_object(function->context()->global_object());
Handle<Context> native_context(global_object->native_context());
Handle<ScriptContextTable> script_context_table(
native_context->script_context_table());
- Handle<String> clashed_name;
Object* name_clash_result =
FindNameClash(scope_info, global_object, script_context_table);
if (isolate->has_pending_exception()) return name_clash_result;
+ // Script contexts have a canonical empty function as their closure, not the
+ // anonymous closure containing the global code. See
+ // FullCodeGenerator::PushFunctionArgumentForContextAllocation.
+ Handle<JSFunction> closure(
+ function->shared()->IsBuiltin() ? *function : native_context->closure());
Handle<Context> result =
- isolate->factory()->NewScriptContext(function, scope_info);
+ isolate->factory()->NewScriptContext(closure, scope_info);
+
+ result->InitializeGlobalSlots();
DCHECK(function->context() == isolate->context());
- DCHECK(function->context()->global_object() == result->global_object());
+ DCHECK(*global_object == result->global_object());
Handle<ScriptContextTable> new_script_context_table =
ScriptContextTable::Extend(script_context_table, result);
@@ -598,31 +823,9 @@
RUNTIME_FUNCTION(Runtime_PushWithContext) {
HandleScope scope(isolate);
- DCHECK(args.length() == 2);
- Handle<JSReceiver> extension_object;
- if (args[0]->IsJSReceiver()) {
- extension_object = args.at<JSReceiver>(0);
- } else {
- // Try to convert the object to a proper JavaScript object.
- MaybeHandle<JSReceiver> maybe_object =
- Object::ToObject(isolate, args.at<Object>(0));
- if (!maybe_object.ToHandle(&extension_object)) {
- Handle<Object> handle = args.at<Object>(0);
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewTypeError("with_expression", HandleVector(&handle, 1)));
- }
- }
-
- Handle<JSFunction> function;
- if (args[1]->IsSmi()) {
- // A smi sentinel indicates a context nested inside global code rather
- // than some function. There is a canonical empty function that can be
- // gotten from the native context.
- function = handle(isolate->native_context()->closure());
- } else {
- function = args.at<JSFunction>(1);
- }
-
+ DCHECK_EQ(2, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Handle<Context> current(isolate->context());
Handle<Context> context =
isolate->factory()->NewWithContext(function, current, extension_object);
@@ -633,18 +836,10 @@
RUNTIME_FUNCTION(Runtime_PushCatchContext) {
HandleScope scope(isolate);
- DCHECK(args.length() == 3);
+ DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
- Handle<JSFunction> function;
- if (args[2]->IsSmi()) {
- // A smi sentinel indicates a context nested inside global code rather
- // than some function. There is a canonical empty function that can be
- // gotten from the native context.
- function = handle(isolate->native_context()->closure());
- } else {
- function = args.at<JSFunction>(2);
- }
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
Handle<Context> current(isolate->context());
Handle<Context> context = isolate->factory()->NewCatchContext(
function, current, name, thrown_object);
@@ -655,17 +850,9 @@
RUNTIME_FUNCTION(Runtime_PushBlockContext) {
HandleScope scope(isolate);
- DCHECK(args.length() == 2);
+ DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
- Handle<JSFunction> function;
- if (args[1]->IsSmi()) {
- // A smi sentinel indicates a context nested inside global code rather
- // than some function. There is a canonical empty function that can be
- // gotten from the native context.
- function = handle(isolate->native_context()->closure());
- } else {
- function = args.at<JSFunction>(1);
- }
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Handle<Context> current(isolate->context());
Handle<Context> context =
isolate->factory()->NewBlockContext(function, current, scope_info);
@@ -707,7 +894,7 @@
Context* previous = isolate->context();
context->set_previous(previous);
context->set_closure(previous->closure());
- context->set_global_object(previous->global_object());
+ context->set_native_context(previous->native_context());
isolate->set_context(*context);
// Find hosting scope and initialize internal variable holding module there.
@@ -737,7 +924,8 @@
case VAR:
case LET:
case CONST:
- case CONST_LEGACY: {
+ case CONST_LEGACY:
+ case IMPORT: {
PropertyAttributes attr =
IsImmutableVariableMode(mode) ? FROZEN : SEALED;
Handle<AccessorInfo> info =
@@ -748,14 +936,6 @@
USE(result);
break;
}
- case MODULE: {
- Object* referenced_context = Context::cast(host_context)->get(index);
- Handle<JSModule> value(Context::cast(referenced_context)->module());
- JSObject::SetOwnPropertyIgnoreAttributes(module, name, value, FROZEN)
- .Assert();
- break;
- }
- case INTERNAL:
case TEMPORARY:
case DYNAMIC:
case DYNAMIC_GLOBAL:
@@ -764,7 +944,10 @@
}
}
- JSObject::PreventExtensions(module).Assert();
+ if (JSObject::PreventExtensions(module, Object::THROW_ON_ERROR)
+ .IsNothing()) {
+ DCHECK(false);
+ }
}
DCHECK(!isolate->has_pending_exception());
@@ -788,6 +971,8 @@
// If the slot was not found the result is true.
if (holder.is_null()) {
+ // In case of JSProxy, an exception might have been thrown.
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
return isolate->heap()->true_value();
}
@@ -796,29 +981,26 @@
return isolate->heap()->false_value();
}
- // The slot was found in a JSObject, either a context extension object,
+ // The slot was found in a JSReceiver, either a context extension object,
// the global object, or the subject of a with. Try to delete it
// (respecting DONT_DELETE).
- Handle<JSObject> object = Handle<JSObject>::cast(holder);
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
- JSReceiver::DeleteProperty(object, name));
- return *result;
+ Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
+ Maybe<bool> result = JSReceiver::DeleteProperty(object, name);
+ MAYBE_RETURN(result, isolate->heap()->exception());
+ return isolate->heap()->ToBoolean(result.FromJust());
}
static Object* ComputeReceiverForNonGlobal(Isolate* isolate, JSObject* holder) {
- DCHECK(!holder->IsGlobalObject());
- Context* top = isolate->context();
- // Get the context extension function.
- JSFunction* context_extension_function =
- top->native_context()->context_extension_function();
+ DCHECK(!holder->IsJSGlobalObject());
+
// If the holder isn't a context extension object, we just return it
// as the receiver. This allows arguments objects to be used as
// receivers, but only if they are put in the context scope chain
// explicitly via a with-statement.
- Object* constructor = holder->map()->constructor();
- if (constructor != context_extension_function) return holder;
+ if (holder->map()->instance_type() != JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
+ return holder;
+ }
// Fall back to using the global object as the implicit receiver if
// the property turns out to be a local variable allocated in a
// context extension object - introduced via eval.
@@ -847,8 +1029,7 @@
return MakePair(isolate->heap()->exception(), NULL);
}
- // If the index is non-negative, the slot has been found in a context.
- if (index >= 0) {
+ if (index != Context::kNotFound) {
DCHECK(holder->IsContext());
// If the "property" we were looking for is a local variable, the
// receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
@@ -859,11 +1040,9 @@
case MUTABLE_CHECK_INITIALIZED:
case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
if (value->IsTheHole()) {
- Handle<Object> error;
- MaybeHandle<Object> maybe_error =
- isolate->factory()->NewReferenceError("not_defined",
- HandleVector(&name, 1));
- if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
+ Handle<Object> error = isolate->factory()->NewReferenceError(
+ MessageTemplate::kNotDefined, name);
+ isolate->Throw(*error);
return MakePair(isolate->heap()->exception(), NULL);
}
// FALLTHROUGH
@@ -889,16 +1068,9 @@
// property from it.
if (!holder.is_null()) {
Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
-#ifdef DEBUG
- if (!object->IsJSProxy()) {
- Maybe<bool> maybe = JSReceiver::HasProperty(object, name);
- DCHECK(maybe.has_value);
- DCHECK(maybe.value);
- }
-#endif
// GetProperty below can cause GC.
Handle<Object> receiver_handle(
- object->IsGlobalObject()
+ object->IsJSGlobalObject()
? Object::cast(isolate->heap()->undefined_value())
: object->IsJSProxy() ? static_cast<Object*>(*object)
: ComputeReceiverForNonGlobal(
@@ -916,10 +1088,9 @@
if (throw_error) {
// The property doesn't exist - throw exception.
- Handle<Object> error;
- MaybeHandle<Object> maybe_error = isolate->factory()->NewReferenceError(
- "not_defined", HandleVector(&name, 1));
- if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
+ Handle<Object> error = isolate->factory()->NewReferenceError(
+ MessageTemplate::kNotDefined, name);
+ isolate->Throw(*error);
return MakePair(isolate->heap()->exception(), NULL);
} else {
// The property doesn't exist - return undefined.
@@ -946,7 +1117,7 @@
CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
- CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
+ CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3);
int index;
PropertyAttributes attributes;
@@ -954,18 +1125,25 @@
BindingFlags binding_flags;
Handle<Object> holder =
context->Lookup(name, flags, &index, &attributes, &binding_flags);
- // In case of JSProxy, an exception might have been thrown.
- if (isolate->has_pending_exception()) return isolate->heap()->exception();
+ if (holder.is_null()) {
+ // In case of JSProxy, an exception might have been thrown.
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
+ }
// The property was found in a context slot.
- if (index >= 0) {
+ if (index != Context::kNotFound) {
+ if ((binding_flags == MUTABLE_CHECK_INITIALIZED ||
+ binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) &&
+ Handle<Context>::cast(holder)->is_the_hole(index)) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
+ }
if ((attributes & READ_ONLY) == 0) {
Handle<Context>::cast(holder)->set(index, *value);
- } else if (strict_mode == STRICT) {
+ } else if (is_strict(language_mode)) {
// Setting read only property in strict mode.
THROW_NEW_ERROR_RETURN_FAILURE(
- isolate,
- NewTypeError("strict_cannot_assign", HandleVector(&name, 1)));
+ isolate, NewTypeError(MessageTemplate::kStrictCannotAssign, name));
}
return *value;
}
@@ -977,43 +1155,49 @@
if (attributes != ABSENT) {
// The property exists on the holder.
object = Handle<JSReceiver>::cast(holder);
- } else if (strict_mode == STRICT) {
+ } else if (is_strict(language_mode)) {
// If absent in strict mode: throw.
THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewReferenceError("not_defined", HandleVector(&name, 1)));
+ isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
} else {
// If absent in sloppy mode: add the property to the global object.
object = Handle<JSReceiver>(context->global_object());
}
RETURN_FAILURE_ON_EXCEPTION(
- isolate, Object::SetProperty(object, name, value, strict_mode));
+ isolate, Object::SetProperty(object, name, value, language_mode));
return *value;
}
-RUNTIME_FUNCTION(Runtime_GetArgumentsProperty) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_ArgumentsLength) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 0);
+ int argument_count = 0;
+ GetCallerArguments(isolate, 0, &argument_count);
+ return Smi::FromInt(argument_count);
+}
+
+
+RUNTIME_FUNCTION(Runtime_Arguments) {
+ HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
- // Compute the frame holding the arguments.
- JavaScriptFrameIterator it(isolate);
- it.AdvanceToArgumentsFrame();
- JavaScriptFrame* frame = it.frame();
-
- // Get the actual number of provided arguments.
- const uint32_t n = frame->ComputeParametersCount();
+ // Determine the actual arguments passed to the function.
+ int argument_count_signed = 0;
+ base::SmartArrayPointer<Handle<Object>> arguments =
+ GetCallerArguments(isolate, 0, &argument_count_signed);
+ const uint32_t argument_count = argument_count_signed;
// Try to convert the key to an index. If successful and within
// index return the the argument from the frame.
- uint32_t index;
- if (raw_key->ToArrayIndex(&index) && index < n) {
- return frame->GetParameter(index);
+ uint32_t index = 0;
+ if (raw_key->ToArrayIndex(&index) && index < argument_count) {
+ return *arguments[index];
}
- HandleScope scope(isolate);
if (raw_key->IsSymbol()) {
Handle<Symbol> symbol = Handle<Symbol>::cast(raw_key);
if (Name::Equals(symbol, isolate->factory()->iterator_symbol())) {
@@ -1031,13 +1215,13 @@
// Convert the key to a string.
Handle<Object> converted;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, converted,
- Execution::ToString(isolate, raw_key));
+ Object::ToString(isolate, raw_key));
Handle<String> key = Handle<String>::cast(converted);
// Try to convert the string key into an array index.
if (key->AsArrayIndex(&index)) {
- if (index < n) {
- return frame->GetParameter(index);
+ if (index < argument_count) {
+ return *arguments[index];
} else {
Handle<Object> initial_prototype(isolate->initial_object_prototype());
Handle<Object> result;
@@ -1050,14 +1234,14 @@
// Handle special arguments properties.
if (String::Equals(isolate->factory()->length_string(), key)) {
- return Smi::FromInt(n);
+ return Smi::FromInt(argument_count);
}
if (String::Equals(isolate->factory()->callee_string(), key)) {
- JSFunction* function = frame->function();
- if (function->shared()->strict_mode() == STRICT) {
+ JavaScriptFrameIterator it(isolate);
+ JSFunction* function = it.frame()->function();
+ if (is_strict(function->shared()->language_mode())) {
THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewTypeError("strict_arguments_callee",
- HandleVector<Object>(NULL, 0)));
+ isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
}
return function;
}
@@ -1069,20 +1253,5 @@
Object::GetProperty(isolate->initial_object_prototype(), key));
return *result;
}
-
-
-RUNTIME_FUNCTION(RuntimeReference_ArgumentsLength) {
- SealHandleScope shs(isolate);
- DCHECK(args.length() == 0);
- JavaScriptFrameIterator it(isolate);
- JavaScriptFrame* frame = it.frame();
- return Smi::FromInt(frame->GetArgumentsLength());
-}
-
-
-RUNTIME_FUNCTION(RuntimeReference_Arguments) {
- SealHandleScope shs(isolate);
- return __RT_impl_Runtime_GetArgumentsProperty(args, isolate);
-}
-}
-} // namespace v8::internal
+} // namespace internal
+} // namespace v8