summaryrefslogtreecommitdiffstats
path: root/chromium/v8/src/runtime.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/runtime.cc')
-rw-r--r--chromium/v8/src/runtime.cc7458
1 files changed, 3875 insertions, 3583 deletions
diff --git a/chromium/v8/src/runtime.cc b/chromium/v8/src/runtime.cc
index 8333380e83b..36b3177b7c0 100644
--- a/chromium/v8/src/runtime.cc
+++ b/chromium/v8/src/runtime.cc
@@ -1,74 +1,51 @@
// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include <stdlib.h>
#include <limits>
-#include "v8.h"
-
-#include "accessors.h"
-#include "allocation-site-scopes.h"
-#include "api.h"
-#include "arguments.h"
-#include "bootstrapper.h"
-#include "codegen.h"
-#include "compilation-cache.h"
-#include "compiler.h"
-#include "cpu.h"
-#include "cpu-profiler.h"
-#include "dateparser-inl.h"
-#include "debug.h"
-#include "deoptimizer.h"
-#include "date.h"
-#include "execution.h"
-#include "full-codegen.h"
-#include "global-handles.h"
-#include "isolate-inl.h"
-#include "jsregexp.h"
-#include "jsregexp-inl.h"
-#include "json-parser.h"
-#include "json-stringifier.h"
-#include "liveedit.h"
-#include "misc-intrinsics.h"
-#include "parser.h"
-#include "platform.h"
-#include "runtime-profiler.h"
-#include "runtime.h"
-#include "scopeinfo.h"
-#include "smart-pointers.h"
-#include "string-search.h"
-#include "stub-cache.h"
-#include "uri.h"
-#include "v8conversions.h"
-#include "v8threads.h"
-#include "vm-state-inl.h"
+#include "src/v8.h"
+
+#include "src/accessors.h"
+#include "src/allocation-site-scopes.h"
+#include "src/api.h"
+#include "src/arguments.h"
+#include "src/bootstrapper.h"
+#include "src/codegen.h"
+#include "src/compilation-cache.h"
+#include "src/compiler.h"
+#include "src/conversions.h"
+#include "src/cpu.h"
+#include "src/cpu-profiler.h"
+#include "src/dateparser-inl.h"
+#include "src/debug.h"
+#include "src/deoptimizer.h"
+#include "src/date.h"
+#include "src/execution.h"
+#include "src/full-codegen.h"
+#include "src/global-handles.h"
+#include "src/isolate-inl.h"
+#include "src/jsregexp.h"
+#include "src/jsregexp-inl.h"
+#include "src/json-parser.h"
+#include "src/json-stringifier.h"
+#include "src/liveedit.h"
+#include "src/misc-intrinsics.h"
+#include "src/parser.h"
+#include "src/platform.h"
+#include "src/runtime-profiler.h"
+#include "src/runtime.h"
+#include "src/scopeinfo.h"
+#include "src/smart-pointers.h"
+#include "src/string-search.h"
+#include "src/stub-cache.h"
+#include "src/uri.h"
+#include "src/v8threads.h"
+#include "src/vm-state-inl.h"
#ifdef V8_I18N_SUPPORT
-#include "i18n.h"
+#include "src/i18n.h"
#include "unicode/brkiter.h"
#include "unicode/calendar.h"
#include "unicode/coll.h"
@@ -105,6 +82,12 @@ namespace internal {
#define RUNTIME_ASSERT(value) \
if (!(value)) return isolate->ThrowIllegalOperation();
+#define RUNTIME_ASSERT_HANDLIFIED(value, T) \
+ if (!(value)) { \
+ isolate->ThrowIllegalOperation(); \
+ return MaybeHandle<T>(); \
+ }
+
// Cast the given object to a value of the specified type and store
// it in a variable with the given name. If the object is not of the
// expected type call IllegalOperation and return.
@@ -116,6 +99,10 @@ namespace internal {
RUNTIME_ASSERT(args[index]->Is##Type()); \
Handle<Type> name = args.at<Type>(index);
+#define CONVERT_NUMBER_ARG_HANDLE_CHECKED(name, index) \
+ RUNTIME_ASSERT(args[index]->IsNumber()); \
+ Handle<Object> name = args.at<Object>(index);
+
// Cast the given object to a boolean and store it in a variable with
// the given name. If the object is not a boolean call IllegalOperation
// and return.
@@ -153,25 +140,13 @@ namespace internal {
PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
-// Assert that the given argument has a valid value for a StrictModeFlag
-// and store it in a StrictModeFlag variable with the given name.
+// Assert that the given argument has a valid value for a StrictMode
+// and store it in a StrictMode variable with the given name.
#define CONVERT_STRICT_MODE_ARG_CHECKED(name, index) \
RUNTIME_ASSERT(args[index]->IsSmi()); \
- RUNTIME_ASSERT(args.smi_at(index) == kStrictMode || \
- args.smi_at(index) == kNonStrictMode); \
- StrictModeFlag name = \
- static_cast<StrictModeFlag>(args.smi_at(index));
-
-
-// Assert that the given argument has a valid value for a LanguageMode
-// and store it in a LanguageMode variable with the given name.
-#define CONVERT_LANGUAGE_MODE_ARG(name, index) \
- ASSERT(args[index]->IsSmi()); \
- ASSERT(args.smi_at(index) == CLASSIC_MODE || \
- args.smi_at(index) == STRICT_MODE || \
- args.smi_at(index) == EXTENDED_MODE); \
- LanguageMode name = \
- static_cast<LanguageMode>(args.smi_at(index));
+ RUNTIME_ASSERT(args.smi_at(index) == STRICT || \
+ args.smi_at(index) == SLOPPY); \
+ StrictMode name = static_cast<StrictMode>(args.smi_at(index));
static Handle<Map> ComputeObjectLiteralMap(
@@ -221,19 +196,17 @@ static Handle<Map> ComputeObjectLiteralMap(
return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
}
*is_result_from_cache = false;
- return isolate->factory()->CopyMap(
- Handle<Map>(context->object_function()->initial_map()),
- number_of_properties);
+ return Map::Create(handle(context->object_function()), number_of_properties);
}
-static Handle<Object> CreateLiteralBoilerplate(
+MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
Isolate* isolate,
Handle<FixedArray> literals,
Handle<FixedArray> constant_properties);
-static Handle<Object> CreateObjectLiteralBoilerplate(
+MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
Isolate* isolate,
Handle<FixedArray> literals,
Handle<FixedArray> constant_properties,
@@ -259,9 +232,11 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
constant_properties,
&is_result_from_cache);
+ PretenureFlag pretenure_flag =
+ isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
+
Handle<JSObject> boilerplate =
- isolate->factory()->NewJSObjectFromMap(
- map, isolate->heap()->GetPretenureMode());
+ isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
// Normalize the elements of the boilerplate to save space if needed.
if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
@@ -270,13 +245,14 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
int length = constant_properties->length();
bool should_transform =
!is_result_from_cache && boilerplate->HasFastProperties();
- if (should_transform || has_function_literal) {
- // Normalize the properties of object to avoid n^2 behavior
- // when extending the object multiple properties. Indicate the number of
- // properties to be added.
+ bool should_normalize = should_transform || has_function_literal;
+ if (should_normalize) {
+ // TODO(verwaest): We might not want to ever normalize here.
JSObject::NormalizeProperties(
boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
}
+ Object::ValueType value_type = should_normalize
+ ? Object::FORCE_TAGGED : Object::OPTIMAL_REPRESENTATION;
// TODO(verwaest): Support tracking representations in the boilerplate.
for (int index = 0; index < length; index +=2) {
@@ -286,28 +262,30 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
// The value contains the constant_properties of a
// simple object or array literal.
Handle<FixedArray> array = Handle<FixedArray>::cast(value);
- value = CreateLiteralBoilerplate(isolate, literals, array);
- if (value.is_null()) return value;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value,
+ CreateLiteralBoilerplate(isolate, literals, array),
+ Object);
}
- Handle<Object> result;
+ MaybeHandle<Object> maybe_result;
uint32_t element_index = 0;
StoreMode mode = value->IsJSObject() ? FORCE_FIELD : ALLOW_AS_CONSTANT;
if (key->IsInternalizedString()) {
if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
// Array index as string (uint32).
- result = JSObject::SetOwnElement(
- boilerplate, element_index, value, kNonStrictMode);
+ maybe_result = JSObject::SetOwnElement(
+ boilerplate, element_index, value, SLOPPY);
} else {
Handle<String> name(String::cast(*key));
ASSERT(!name->AsArrayIndex(&element_index));
- result = JSObject::SetLocalPropertyIgnoreAttributes(
+ maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(
boilerplate, name, value, NONE,
- Object::OPTIMAL_REPRESENTATION, mode);
+ value_type, mode);
}
} else if (key->ToArrayIndex(&element_index)) {
// Array index (uint32).
- result = JSObject::SetOwnElement(
- boilerplate, element_index, value, kNonStrictMode);
+ maybe_result = JSObject::SetOwnElement(
+ boilerplate, element_index, value, SLOPPY);
} else {
// Non-uint32 number.
ASSERT(key->IsNumber());
@@ -315,17 +293,16 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
char arr[100];
Vector<char> buffer(arr, ARRAY_SIZE(arr));
const char* str = DoubleToCString(num, buffer);
- Handle<String> name =
- isolate->factory()->NewStringFromAscii(CStrVector(str));
- result = JSObject::SetLocalPropertyIgnoreAttributes(
+ Handle<String> name = isolate->factory()->NewStringFromAsciiChecked(str);
+ maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(
boilerplate, name, value, NONE,
- Object::OPTIMAL_REPRESENTATION, mode);
+ value_type, mode);
}
// If setting the property on the boilerplate throws an
// exception, the exception is converted to an empty handle in
// the handle based operations. In that case, we need to
// convert back to an exception.
- if (result.is_null()) return result;
+ RETURN_ON_EXCEPTION(isolate, maybe_result, Object);
}
// Transform to fast properties if necessary. For object literals with
@@ -341,25 +318,30 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
}
-MaybeObject* TransitionElements(Handle<Object> object,
- ElementsKind to_kind,
- Isolate* isolate) {
+MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
+ Handle<Object> object,
+ ElementsKind to_kind,
+ Isolate* isolate) {
HandleScope scope(isolate);
- if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
+ if (!object->IsJSObject()) {
+ isolate->ThrowIllegalOperation();
+ return MaybeHandle<Object>();
+ }
ElementsKind from_kind =
Handle<JSObject>::cast(object)->map()->elements_kind();
if (Map::IsValidElementsTransition(from_kind, to_kind)) {
JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
- return *object;
+ return object;
}
- return isolate->ThrowIllegalOperation();
+ isolate->ThrowIllegalOperation();
+ return MaybeHandle<Object>();
}
static const int kSmiLiteralMinimumLength = 1024;
-Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
+MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate(
Isolate* isolate,
Handle<FixedArray> literals,
Handle<FixedArray> elements) {
@@ -367,23 +349,25 @@ Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
Handle<JSFunction> constructor(
JSFunction::NativeContextFromLiterals(*literals)->array_function());
+ PretenureFlag pretenure_flag =
+ isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
+
Handle<JSArray> object = Handle<JSArray>::cast(
- isolate->factory()->NewJSObject(
- constructor, isolate->heap()->GetPretenureMode()));
+ isolate->factory()->NewJSObject(constructor, pretenure_flag));
ElementsKind constant_elements_kind =
static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
Handle<FixedArrayBase> constant_elements_values(
FixedArrayBase::cast(elements->get(1)));
- ASSERT(IsFastElementsKind(constant_elements_kind));
- Context* native_context = isolate->context()->native_context();
- Object* maybe_maps_array = native_context->js_array_maps();
- ASSERT(!maybe_maps_array->IsUndefined());
- Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
- constant_elements_kind);
- ASSERT(maybe_map->IsMap());
- object->set_map(Map::cast(maybe_map));
+ { DisallowHeapAllocation no_gc;
+ ASSERT(IsFastElementsKind(constant_elements_kind));
+ Context* native_context = isolate->context()->native_context();
+ Object* maps_array = native_context->js_array_maps();
+ ASSERT(!maps_array->IsUndefined());
+ Object* map = FixedArray::cast(maps_array)->get(constant_elements_kind);
+ object->set_map(Map::cast(map));
+ }
Handle<FixedArrayBase> copied_elements_values;
if (IsFastDoubleElementsKind(constant_elements_kind)) {
@@ -411,14 +395,15 @@ Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
isolate->factory()->CopyFixedArray(fixed_array_values);
copied_elements_values = fixed_array_values_copy;
for (int i = 0; i < fixed_array_values->length(); i++) {
- Object* current = fixed_array_values->get(i);
- if (current->IsFixedArray()) {
+ if (fixed_array_values->get(i)->IsFixedArray()) {
// The value contains the constant_properties of a
// simple object or array literal.
Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
- Handle<Object> result =
- CreateLiteralBoilerplate(isolate, literals, fa);
- if (result.is_null()) return result;
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result,
+ CreateLiteralBoilerplate(isolate, literals, fa),
+ Object);
fixed_array_values_copy->set(i, *result);
}
}
@@ -434,20 +419,19 @@ Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
ElementsKind elements_kind = object->GetElementsKind();
if (!IsFastObjectElementsKind(elements_kind)) {
if (IsFastHoleyElementsKind(elements_kind)) {
- CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS,
- isolate)->IsFailure());
+ TransitionElements(object, FAST_HOLEY_ELEMENTS, isolate).Check();
} else {
- CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
+ TransitionElements(object, FAST_ELEMENTS, isolate).Check();
}
}
}
- object->ValidateElements();
+ JSObject::ValidateElements(object);
return object;
}
-static Handle<Object> CreateLiteralBoilerplate(
+MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
Isolate* isolate,
Handle<FixedArray> literals,
Handle<FixedArray> array) {
@@ -471,12 +455,12 @@ static Handle<Object> CreateLiteralBoilerplate(
isolate, literals, elements);
default:
UNREACHABLE();
- return Handle<Object>::null();
+ return MaybeHandle<Object>();
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
+RUNTIME_FUNCTION(RuntimeHidden_CreateObjectLiteral) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
@@ -486,24 +470,29 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
+ RUNTIME_ASSERT(literals_index >= 0 && literals_index < literals->length());
+
// Check if boilerplate exists. If not, create it first.
Handle<Object> literal_site(literals->get(literals_index), isolate);
Handle<AllocationSite> site;
Handle<JSObject> boilerplate;
if (*literal_site == isolate->heap()->undefined_value()) {
- Handle<Object> raw_boilerplate = CreateObjectLiteralBoilerplate(
- isolate,
- literals,
- constant_properties,
- should_have_fast_elements,
- has_function_literal);
- RETURN_IF_EMPTY_HANDLE(isolate, raw_boilerplate);
+ Handle<Object> raw_boilerplate;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, raw_boilerplate,
+ CreateObjectLiteralBoilerplate(
+ isolate,
+ literals,
+ constant_properties,
+ should_have_fast_elements,
+ has_function_literal));
boilerplate = Handle<JSObject>::cast(raw_boilerplate);
AllocationSiteCreationContext creation_context(isolate);
site = creation_context.EnterNewScope();
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::DeepWalk(boilerplate, &creation_context));
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate,
+ JSObject::DeepWalk(boilerplate, &creation_context));
creation_context.ExitScope(site, boilerplate);
// Update the functions literal and return the boilerplate.
@@ -516,14 +505,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
AllocationSiteUsageContext usage_context(isolate, site, true);
usage_context.EnterNewScope();
- Handle<Object> copy = JSObject::DeepCopy(boilerplate, &usage_context);
+ MaybeHandle<Object> maybe_copy = JSObject::DeepCopy(
+ boilerplate, &usage_context);
usage_context.ExitScope(site, boilerplate);
- RETURN_IF_EMPTY_HANDLE(isolate, copy);
+ Handle<Object> copy;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, copy, maybe_copy);
return *copy;
}
-static Handle<AllocationSite> GetLiteralAllocationSite(
+MUST_USE_RESULT static MaybeHandle<AllocationSite> GetLiteralAllocationSite(
Isolate* isolate,
Handle<FixedArray> literals,
int literals_index,
@@ -533,9 +524,11 @@ static Handle<AllocationSite> GetLiteralAllocationSite(
Handle<AllocationSite> site;
if (*literal_site == isolate->heap()->undefined_value()) {
ASSERT(*elements != isolate->heap()->empty_fixed_array());
- Handle<Object> boilerplate =
- Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
- if (boilerplate.is_null()) return Handle<AllocationSite>::null();
+ Handle<Object> boilerplate;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, boilerplate,
+ Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements),
+ AllocationSite);
AllocationSiteCreationContext creation_context(isolate);
site = creation_context.EnterNewScope();
@@ -554,14 +547,18 @@ static Handle<AllocationSite> GetLiteralAllocationSite(
}
-static MaybeObject* CreateArrayLiteralImpl(Isolate* isolate,
+static MaybeHandle<JSObject> CreateArrayLiteralImpl(Isolate* isolate,
Handle<FixedArray> literals,
int literals_index,
Handle<FixedArray> elements,
int flags) {
- Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
- literals_index, elements);
- RETURN_IF_EMPTY_HANDLE(isolate, site);
+ RUNTIME_ASSERT_HANDLIFIED(literals_index >= 0 &&
+ literals_index < literals->length(), JSObject);
+ Handle<AllocationSite> site;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, site,
+ GetLiteralAllocationSite(isolate, literals, literals_index, elements),
+ JSObject);
bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
@@ -570,15 +567,14 @@ static MaybeObject* CreateArrayLiteralImpl(Isolate* isolate,
JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
? JSObject::kNoHints
: JSObject::kObjectIsShallowArray;
- Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
- hints);
+ MaybeHandle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
+ hints);
usage_context.ExitScope(site, boilerplate);
- RETURN_IF_EMPTY_HANDLE(isolate, copy);
- return *copy;
+ return copy;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
+RUNTIME_FUNCTION(RuntimeHidden_CreateArrayLiteral) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
@@ -586,50 +582,83 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
- return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
- flags);
+ Handle<JSObject> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
+ CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
+ flags));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralStubBailout) {
+RUNTIME_FUNCTION(RuntimeHidden_CreateArrayLiteralStubBailout) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
CONVERT_SMI_ARG_CHECKED(literals_index, 1);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
- return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
- ArrayLiteral::kShallowElements);
+ Handle<JSObject> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
+ CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
+ ArrayLiteral::kShallowElements));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
+RUNTIME_FUNCTION(Runtime_CreateSymbol) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- Handle<Object> name(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
- Symbol* symbol;
- MaybeObject* maybe = isolate->heap()->AllocateSymbol();
- if (!maybe->To(&symbol)) return maybe;
+ Handle<Symbol> symbol = isolate->factory()->NewSymbol();
if (name->IsString()) symbol->set_name(*name);
- return symbol;
+ return *symbol;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreatePrivateSymbol) {
+RUNTIME_FUNCTION(Runtime_CreatePrivateSymbol) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- Handle<Object> name(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
- Symbol* symbol;
- MaybeObject* maybe = isolate->heap()->AllocatePrivateSymbol();
- if (!maybe->To(&symbol)) return maybe;
+ Handle<Symbol> symbol = isolate->factory()->NewPrivateSymbol();
if (name->IsString()) symbol->set_name(*name);
- return symbol;
+ return *symbol;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolName) {
+RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
+ Handle<JSObject> registry = isolate->GetSymbolRegistry();
+ Handle<String> part = isolate->factory()->private_intern_string();
+ Handle<Object> privates;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, privates, Object::GetPropertyOrElement(registry, part));
+ Handle<Object> symbol;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, symbol, Object::GetPropertyOrElement(privates, name));
+ if (!symbol->IsSymbol()) {
+ ASSERT(symbol->IsUndefined());
+ symbol = isolate->factory()->NewPrivateSymbol();
+ Handle<Symbol>::cast(symbol)->set_name(*name);
+ JSObject::SetProperty(Handle<JSObject>::cast(privates),
+ name, symbol, NONE, STRICT).Assert();
+ }
+ return *symbol;
+}
+
+
+RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0);
+ return *Object::ToObject(isolate, symbol).ToHandleChecked();
+}
+
+
+RUNTIME_FUNCTION(Runtime_SymbolDescription) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(Symbol, symbol, 0);
@@ -637,7 +666,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolName) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolIsPrivate) {
+RUNTIME_FUNCTION(Runtime_SymbolRegistry) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 0);
+ return *isolate->GetSymbolRegistry();
+}
+
+
+RUNTIME_FUNCTION(Runtime_SymbolIsPrivate) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(Symbol, symbol, 0);
@@ -645,49 +681,47 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolIsPrivate) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_CreateJSProxy) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
- Object* prototype = args[1];
- Object* used_prototype =
- prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
- return isolate->heap()->AllocateJSProxy(handler, used_prototype);
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
+ if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
+ return *isolate->factory()->NewJSProxy(handler, prototype);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_CreateJSFunctionProxy) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 4);
- CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
- Object* call_trap = args[1];
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, call_trap, 1);
RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
- CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
- Object* prototype = args[3];
- Object* used_prototype =
- prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
- return isolate->heap()->AllocateJSFunctionProxy(
- handler, call_trap, construct_trap, used_prototype);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, construct_trap, 2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 3);
+ if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
+ return *isolate->factory()->NewJSFunctionProxy(
+ handler, call_trap, construct_trap, prototype);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
+RUNTIME_FUNCTION(Runtime_IsJSProxy) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* obj = args[0];
+ CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSProxy());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
+RUNTIME_FUNCTION(Runtime_IsJSFunctionProxy) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* obj = args[0];
+ CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
+RUNTIME_FUNCTION(Runtime_GetHandler) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
@@ -695,7 +729,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
+RUNTIME_FUNCTION(Runtime_GetCallTrap) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
@@ -703,7 +737,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
+RUNTIME_FUNCTION(Runtime_GetConstructTrap) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
@@ -711,7 +745,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
+RUNTIME_FUNCTION(Runtime_Fix) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
@@ -731,8 +765,9 @@ void Runtime::FreeArrayBuffer(Isolate* isolate,
size_t allocated_length = NumberToSize(
isolate, phantom_array_buffer->byte_length());
- isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
- -static_cast<int64_t>(allocated_length));
+ reinterpret_cast<v8::Isolate*>(isolate)
+ ->AdjustAmountOfExternalAllocatedMemory(
+ -static_cast<int64_t>(allocated_length));
CHECK(V8::ArrayBufferAllocator() != NULL);
V8::ArrayBufferAllocator()->Free(
phantom_array_buffer->backing_store(),
@@ -777,7 +812,7 @@ bool Runtime::SetupArrayBufferAllocatingData(
data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
} else {
data =
- V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
+ V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
}
if (data == NULL) return false;
} else {
@@ -786,47 +821,57 @@ bool Runtime::SetupArrayBufferAllocatingData(
SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
- isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
+ reinterpret_cast<v8::Isolate*>(isolate)
+ ->AdjustAmountOfExternalAllocatedMemory(allocated_length);
return true;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
+void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) {
+ Isolate* isolate = array_buffer->GetIsolate();
+ for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate);
+ !view_obj->IsUndefined();) {
+ Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj));
+ if (view->IsJSTypedArray()) {
+ JSTypedArray::cast(*view)->Neuter();
+ } else if (view->IsJSDataView()) {
+ JSDataView::cast(*view)->Neuter();
+ } else {
+ UNREACHABLE();
+ }
+ view_obj = handle(view->weak_next(), isolate);
+ }
+ array_buffer->Neuter();
+}
+
+
+RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
- CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
- size_t allocated_length;
- if (byteLength->IsSmi()) {
- allocated_length = Smi::cast(*byteLength)->value();
- } else {
- ASSERT(byteLength->IsHeapNumber());
- double value = HeapNumber::cast(*byteLength)->value();
-
- ASSERT(value >= 0);
-
- if (value > std::numeric_limits<size_t>::max()) {
- return isolate->Throw(
- *isolate->factory()->NewRangeError("invalid_array_buffer_length",
- HandleVector<Object>(NULL, 0)));
- }
-
- allocated_length = static_cast<size_t>(value);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1);
+ if (!holder->byte_length()->IsUndefined()) {
+ // ArrayBuffer is already initialized; probably a fuzz test.
+ return *holder;
+ }
+ size_t allocated_length = 0;
+ if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) {
+ return isolate->Throw(
+ *isolate->factory()->NewRangeError("invalid_array_buffer_length",
+ HandleVector<Object>(NULL, 0)));
}
-
if (!Runtime::SetupArrayBufferAllocatingData(isolate,
holder, allocated_length)) {
- return isolate->Throw(*isolate->factory()->
- NewRangeError("invalid_array_buffer_length",
- HandleVector<Object>(NULL, 0)));
+ return isolate->Throw(
+ *isolate->factory()->NewRangeError("invalid_array_buffer_length",
+ HandleVector<Object>(NULL, 0)));
}
-
return *holder;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
+RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
@@ -834,18 +879,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
+RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
- CONVERT_DOUBLE_ARG_CHECKED(first, 2);
- size_t start = static_cast<size_t>(first);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2);
+ RUNTIME_ASSERT(!source.is_identical_to(target));
+ size_t start = 0;
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start));
size_t target_length = NumberToSize(isolate, target->byte_length());
if (target_length == 0) return isolate->heap()->undefined_value();
- ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start);
+ size_t source_byte_length = NumberToSize(isolate, source->byte_length());
+ RUNTIME_ASSERT(start <= source_byte_length);
+ RUNTIME_ASSERT(source_byte_length - start >= target_length);
uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
CopyBytes(target_data, source_data + start, target_length);
@@ -853,105 +902,138 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferIsView) {
+RUNTIME_FUNCTION(Runtime_ArrayBufferIsView) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(Object, object, 0);
- return object->IsJSArrayBufferView()
- ? isolate->heap()->true_value()
- : isolate->heap()->false_value();
+ return isolate->heap()->ToBoolean(object->IsJSArrayBufferView());
+}
+
+
+RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0);
+ if (array_buffer->backing_store() == NULL) {
+ CHECK(Smi::FromInt(0) == array_buffer->byte_length());
+ return isolate->heap()->undefined_value();
+ }
+ ASSERT(!array_buffer->is_external());
+ void* backing_store = array_buffer->backing_store();
+ size_t byte_length = NumberToSize(isolate, array_buffer->byte_length());
+ array_buffer->set_is_external(true);
+ Runtime::NeuterArrayBuffer(array_buffer);
+ V8::ArrayBufferAllocator()->Free(backing_store, byte_length);
+ return isolate->heap()->undefined_value();
}
void Runtime::ArrayIdToTypeAndSize(
- int arrayId, ExternalArrayType* array_type, size_t* element_size) {
+ int arrayId,
+ ExternalArrayType* array_type,
+ ElementsKind* external_elements_kind,
+ ElementsKind* fixed_elements_kind,
+ size_t* element_size) {
switch (arrayId) {
- case ARRAY_ID_UINT8:
- *array_type = kExternalUnsignedByteArray;
- *element_size = 1;
- break;
- case ARRAY_ID_INT8:
- *array_type = kExternalByteArray;
- *element_size = 1;
- break;
- case ARRAY_ID_UINT16:
- *array_type = kExternalUnsignedShortArray;
- *element_size = 2;
- break;
- case ARRAY_ID_INT16:
- *array_type = kExternalShortArray;
- *element_size = 2;
- break;
- case ARRAY_ID_UINT32:
- *array_type = kExternalUnsignedIntArray;
- *element_size = 4;
- break;
- case ARRAY_ID_INT32:
- *array_type = kExternalIntArray;
- *element_size = 4;
- break;
- case ARRAY_ID_FLOAT32:
- *array_type = kExternalFloatArray;
- *element_size = 4;
- break;
- case ARRAY_ID_FLOAT64:
- *array_type = kExternalDoubleArray;
- *element_size = 8;
- break;
- case ARRAY_ID_UINT8C:
- *array_type = kExternalPixelArray;
- *element_size = 1;
+#define ARRAY_ID_CASE(Type, type, TYPE, ctype, size) \
+ case ARRAY_ID_##TYPE: \
+ *array_type = kExternal##Type##Array; \
+ *external_elements_kind = EXTERNAL_##TYPE##_ELEMENTS; \
+ *fixed_elements_kind = TYPE##_ELEMENTS; \
+ *element_size = size; \
break;
+
+ TYPED_ARRAYS(ARRAY_ID_CASE)
+#undef ARRAY_ID_CASE
+
default:
UNREACHABLE();
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
+RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
CONVERT_SMI_ARG_CHECKED(arrayId, 1);
- CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2);
- CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
- CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
+ CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset_object, 3);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4);
- ASSERT(holder->GetInternalFieldCount() ==
- v8::ArrayBufferView::kInternalFieldCount);
- for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
- holder->SetInternalField(i, Smi::FromInt(0));
- }
+ RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST &&
+ arrayId <= Runtime::ARRAY_ID_LAST);
- ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
+ ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
size_t element_size = 1; // Bogus initialization.
- Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
+ ElementsKind external_elements_kind =
+ EXTERNAL_INT8_ELEMENTS; // Bogus initialization.
+ ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization.
+ Runtime::ArrayIdToTypeAndSize(arrayId,
+ &array_type,
+ &external_elements_kind,
+ &fixed_elements_kind,
+ &element_size);
+ RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
- holder->set_buffer(*buffer);
- holder->set_byte_offset(*byte_offset_object);
- holder->set_byte_length(*byte_length_object);
+ size_t byte_offset = 0;
+ size_t byte_length = 0;
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset_object, &byte_offset));
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length_object, &byte_length));
+
+ if (maybe_buffer->IsJSArrayBuffer()) {
+ Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
+ size_t array_buffer_byte_length =
+ NumberToSize(isolate, buffer->byte_length());
+ RUNTIME_ASSERT(byte_offset <= array_buffer_byte_length);
+ RUNTIME_ASSERT(array_buffer_byte_length - byte_offset >= byte_length);
+ } else {
+ RUNTIME_ASSERT(maybe_buffer->IsNull());
+ }
- size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
- size_t byte_length = NumberToSize(isolate, *byte_length_object);
- ASSERT(byte_length % element_size == 0);
+ RUNTIME_ASSERT(byte_length % element_size == 0);
size_t length = byte_length / element_size;
if (length > static_cast<unsigned>(Smi::kMaxValue)) {
- return isolate->Throw(*isolate->factory()->
- NewRangeError("invalid_typed_array_length",
- HandleVector<Object>(NULL, 0)));
+ return isolate->Throw(
+ *isolate->factory()->NewRangeError("invalid_typed_array_length",
+ HandleVector<Object>(NULL, 0)));
}
+ // All checks are done, now we can modify objects.
+
+ ASSERT(holder->GetInternalFieldCount() ==
+ v8::ArrayBufferView::kInternalFieldCount);
+ for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
+ holder->SetInternalField(i, Smi::FromInt(0));
+ }
Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
holder->set_length(*length_obj);
- holder->set_weak_next(buffer->weak_first_view());
- buffer->set_weak_first_view(*holder);
+ holder->set_byte_offset(*byte_offset_object);
+ holder->set_byte_length(*byte_length_object);
- Handle<ExternalArray> elements =
- isolate->factory()->NewExternalArray(
- static_cast<int>(length), array_type,
- static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
- holder->set_elements(*elements);
+ if (!maybe_buffer->IsNull()) {
+ Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
+ holder->set_buffer(*buffer);
+ holder->set_weak_next(buffer->weak_first_view());
+ buffer->set_weak_first_view(*holder);
+
+ Handle<ExternalArray> elements =
+ isolate->factory()->NewExternalArray(
+ static_cast<int>(length), array_type,
+ static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
+ Handle<Map> map =
+ JSObject::GetElementsTransitionMap(holder, external_elements_kind);
+ JSObject::SetMapAndElements(holder, map, elements);
+ ASSERT(IsExternalArrayElementsKind(holder->map()->elements_kind()));
+ } else {
+ holder->set_buffer(Smi::FromInt(0));
+ holder->set_weak_next(isolate->heap()->undefined_value());
+ Handle<FixedTypedArrayBase> elements =
+ isolate->factory()->NewFixedTypedArray(
+ static_cast<int>(length), array_type);
+ holder->set_elements(*elements);
+ }
return isolate->heap()->undefined_value();
}
@@ -961,30 +1043,37 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
// initializes backing store using memove.
//
// Returns true if backing store was initialized or false otherwise.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
+RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
CONVERT_SMI_ARG_CHECKED(arrayId, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
- CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 3);
- ASSERT(holder->GetInternalFieldCount() ==
- v8::ArrayBufferView::kInternalFieldCount);
- for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
- holder->SetInternalField(i, Smi::FromInt(0));
- }
+ RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST &&
+ arrayId <= Runtime::ARRAY_ID_LAST);
- ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
+ ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
size_t element_size = 1; // Bogus initialization.
- Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
+ ElementsKind external_elements_kind =
+ EXTERNAL_INT8_ELEMENTS; // Bogus intialization.
+ ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization.
+ Runtime::ArrayIdToTypeAndSize(arrayId,
+ &array_type,
+ &external_elements_kind,
+ &fixed_elements_kind,
+ &element_size);
+
+ RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
if (source->IsJSTypedArray() &&
JSTypedArray::cast(*source)->type() == array_type) {
length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate);
}
- size_t length = NumberToSize(isolate, *length_obj);
+ size_t length = 0;
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *length_obj, &length));
if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
(length > (kMaxInt / element_size))) {
@@ -994,6 +1083,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
}
size_t byte_length = length * element_size;
+ ASSERT(holder->GetInternalFieldCount() ==
+ v8::ArrayBufferView::kInternalFieldCount);
+ for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
+ holder->SetInternalField(i, Smi::FromInt(0));
+ }
+
// NOTE: not initializing backing store.
// We assume that the caller of this function will initialize holder
// with the loop
@@ -1030,7 +1125,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
isolate->factory()->NewExternalArray(
static_cast<int>(length), array_type,
static_cast<uint8_t*>(buffer->backing_store()));
- holder->set_elements(*elements);
+ Handle<Map> map = JSObject::GetElementsTransitionMap(
+ holder, external_elements_kind);
+ JSObject::SetMapAndElements(holder, map, elements);
if (source->IsJSTypedArray()) {
Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
@@ -1038,41 +1135,43 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
if (typed_array->type() == holder->type()) {
uint8_t* backing_store =
static_cast<uint8_t*>(
- JSArrayBuffer::cast(typed_array->buffer())->backing_store());
+ typed_array->GetBuffer()->backing_store());
size_t source_byte_offset =
NumberToSize(isolate, typed_array->byte_offset());
memcpy(
buffer->backing_store(),
backing_store + source_byte_offset,
byte_length);
- return *isolate->factory()->true_value();
- } else {
- return *isolate->factory()->false_value();
+ return isolate->heap()->true_value();
}
}
- return *isolate->factory()->false_value();
+ return isolate->heap()->false_value();
}
-#define TYPED_ARRAY_GETTER(getter, accessor) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \
+#define BUFFER_VIEW_GETTER(Type, getter, accessor) \
+ RUNTIME_FUNCTION(Runtime_##Type##Get##getter) { \
HandleScope scope(isolate); \
ASSERT(args.length() == 1); \
- CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); \
- if (!holder->IsJSTypedArray()) \
- return isolate->Throw(*isolate->factory()->NewTypeError( \
- "not_typed_array", HandleVector<Object>(NULL, 0))); \
- Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder)); \
- return typed_array->accessor(); \
+ CONVERT_ARG_HANDLE_CHECKED(JS##Type, holder, 0); \
+ return holder->accessor(); \
}
-TYPED_ARRAY_GETTER(Buffer, buffer)
-TYPED_ARRAY_GETTER(ByteLength, byte_length)
-TYPED_ARRAY_GETTER(ByteOffset, byte_offset)
-TYPED_ARRAY_GETTER(Length, length)
+BUFFER_VIEW_GETTER(ArrayBufferView, ByteLength, byte_length)
+BUFFER_VIEW_GETTER(ArrayBufferView, ByteOffset, byte_offset)
+BUFFER_VIEW_GETTER(TypedArray, Length, length)
+BUFFER_VIEW_GETTER(DataView, Buffer, buffer)
+
+#undef BUFFER_VIEW_GETTER
+
+RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
+ return *holder->GetBuffer();
+}
-#undef TYPED_ARRAY_GETTER
// Return codes for Runtime_TypedArraySetFastCases.
// Should be synchronized with typedarray.js natives.
@@ -1089,22 +1188,24 @@ enum TypedArraySetResultCodes {
};
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
+RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases) {
HandleScope scope(isolate);
- CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
- CONVERT_ARG_HANDLE_CHECKED(Object, source_obj, 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, offset_obj, 2);
-
- if (!target_obj->IsJSTypedArray())
+ ASSERT(args.length() == 3);
+ if (!args[0]->IsJSTypedArray())
return isolate->Throw(*isolate->factory()->NewTypeError(
"not_typed_array", HandleVector<Object>(NULL, 0)));
- if (!source_obj->IsJSTypedArray())
+ if (!args[1]->IsJSTypedArray())
return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
+ CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target_obj, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, source_obj, 1);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset_obj, 2);
+
Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
- size_t offset = NumberToSize(isolate, *offset_obj);
+ size_t offset = 0;
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *offset_obj, &offset));
size_t target_length = NumberToSize(isolate, target->length());
size_t source_length = NumberToSize(isolate, source->length());
size_t target_byte_length = NumberToSize(isolate, target->byte_length());
@@ -1119,10 +1220,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
size_t source_offset = NumberToSize(isolate, source->byte_offset());
uint8_t* target_base =
static_cast<uint8_t*>(
- JSArrayBuffer::cast(target->buffer())->backing_store()) + target_offset;
+ target->GetBuffer()->backing_store()) + target_offset;
uint8_t* source_base =
static_cast<uint8_t*>(
- JSArrayBuffer::cast(source->buffer())->backing_store()) + source_offset;
+ source->GetBuffer()->backing_store()) + source_offset;
// Typed arrays of the same type: use memmove.
if (target->type() == source->type()) {
@@ -1138,8 +1239,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
target_base + target_byte_length > source_base)) {
// We do not support overlapping ArrayBuffers
ASSERT(
- JSArrayBuffer::cast(target->buffer())->backing_store() ==
- JSArrayBuffer::cast(source->buffer())->backing_store());
+ target->GetBuffer()->backing_store() ==
+ source->GetBuffer()->backing_store());
return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
} else { // Non-overlapping typed arrays
return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
@@ -1147,28 +1248,44 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
+RUNTIME_FUNCTION(Runtime_TypedArrayMaxSizeInHeap) {
+ ASSERT(args.length() == 0);
+ ASSERT_OBJECT_SIZE(
+ FLAG_typed_array_max_size_in_heap + FixedTypedArrayBase::kDataOffset);
+ return Smi::FromInt(FLAG_typed_array_max_size_in_heap);
+}
+
+
+RUNTIME_FUNCTION(Runtime_DataViewInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
- CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset, 2);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length, 3);
ASSERT(holder->GetInternalFieldCount() ==
v8::ArrayBufferView::kInternalFieldCount);
for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
holder->SetInternalField(i, Smi::FromInt(0));
}
+ size_t buffer_length = 0;
+ size_t offset = 0;
+ size_t length = 0;
+ RUNTIME_ASSERT(
+ TryNumberToSize(isolate, buffer->byte_length(), &buffer_length));
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset, &offset));
+ RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length, &length));
+
+ // TODO(jkummerow): When we have a "safe numerics" helper class, use it here.
+ // Entire range [offset, offset + length] must be in bounds.
+ RUNTIME_ASSERT(offset <= buffer_length);
+ RUNTIME_ASSERT(offset + length <= buffer_length);
+ // No overflow.
+ RUNTIME_ASSERT(offset + length >= offset);
holder->set_buffer(*buffer);
- ASSERT(byte_offset->IsNumber());
- ASSERT(
- NumberToSize(isolate, buffer->byte_length()) >=
- NumberToSize(isolate, *byte_offset)
- + NumberToSize(isolate, *byte_length));
holder->set_byte_offset(*byte_offset);
- ASSERT(byte_length->IsNumber());
holder->set_byte_length(*byte_length);
holder->set_weak_next(buffer->weak_first_view());
@@ -1178,30 +1295,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
- return data_view->buffer();
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
- return data_view->byte_offset();
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
- return data_view->byte_length();
-}
-
-
inline static bool NeedToFlipBytes(bool is_little_endian) {
#ifdef V8_TARGET_LITTLE_ENDIAN
return !is_little_endian;
@@ -1317,16 +1410,16 @@ static bool DataViewSetValue(
#define DATA_VIEW_GETTER(TypeName, Type, Converter) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) { \
+ RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) { \
HandleScope scope(isolate); \
ASSERT(args.length() == 3); \
CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
- CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1); \
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \
CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2); \
Type result; \
if (DataViewGetValue( \
isolate, holder, offset, is_little_endian, &result)) { \
- return isolate->heap()->Converter(result); \
+ return *isolate->factory()->Converter(result); \
} else { \
return isolate->Throw(*isolate->factory()->NewRangeError( \
"invalid_data_view_accessor_offset", \
@@ -1334,14 +1427,14 @@ static bool DataViewSetValue(
} \
}
-DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32)
-DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32)
-DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32)
-DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32)
-DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32)
-DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32)
-DATA_VIEW_GETTER(Float32, float, NumberFromDouble)
-DATA_VIEW_GETTER(Float64, double, NumberFromDouble)
+DATA_VIEW_GETTER(Uint8, uint8_t, NewNumberFromUint)
+DATA_VIEW_GETTER(Int8, int8_t, NewNumberFromInt)
+DATA_VIEW_GETTER(Uint16, uint16_t, NewNumberFromUint)
+DATA_VIEW_GETTER(Int16, int16_t, NewNumberFromInt)
+DATA_VIEW_GETTER(Uint32, uint32_t, NewNumberFromUint)
+DATA_VIEW_GETTER(Int32, int32_t, NewNumberFromInt)
+DATA_VIEW_GETTER(Float32, float, NewNumber)
+DATA_VIEW_GETTER(Float64, double, NewNumber)
#undef DATA_VIEW_GETTER
@@ -1399,12 +1492,12 @@ double DataViewConvertValue<double>(double value) {
#define DATA_VIEW_SETTER(TypeName, Type) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) { \
+ RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) { \
HandleScope scope(isolate); \
ASSERT(args.length() == 4); \
CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
- CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1); \
- CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); \
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); \
CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3); \
Type v = DataViewConvertValue<Type>(value->Number()); \
if (DataViewSetValue( \
@@ -1429,208 +1522,288 @@ DATA_VIEW_SETTER(Float64, double)
#undef DATA_VIEW_SETTER
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
+RUNTIME_FUNCTION(Runtime_SetInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
+ Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
holder->set_table(*table);
return *holder;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
+RUNTIME_FUNCTION(Runtime_SetAdd) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<Object> key(args[1], isolate);
- Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
- table = ObjectHashSet::Add(table, key);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+ Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
+ table = OrderedHashSet::Add(table, key);
holder->set_table(*table);
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
+RUNTIME_FUNCTION(Runtime_SetHas) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<Object> key(args[1], isolate);
- Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
- return isolate->heap()->ToBoolean(table->Contains(*key));
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+ Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
+ return isolate->heap()->ToBoolean(table->Contains(key));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
+RUNTIME_FUNCTION(Runtime_SetDelete) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<Object> key(args[1], isolate);
- Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
- table = ObjectHashSet::Remove(table, key);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+ Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
+ bool was_present = false;
+ table = OrderedHashSet::Remove(table, key, &was_present);
+ holder->set_table(*table);
+ return isolate->heap()->ToBoolean(was_present);
+}
+
+
+RUNTIME_FUNCTION(Runtime_SetClear) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
+ Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
+ table = OrderedHashSet::Clear(table);
holder->set_table(*table);
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
+RUNTIME_FUNCTION(Runtime_SetGetSize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
+ Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
return Smi::FromInt(table->NumberOfElements());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
+RUNTIME_FUNCTION(Runtime_SetIteratorInitialize) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 3);
+ CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSSet, set, 1);
+ CONVERT_SMI_ARG_CHECKED(kind, 2)
+ RUNTIME_ASSERT(kind == JSSetIterator::kKindValues ||
+ kind == JSSetIterator::kKindEntries);
+ Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
+ holder->set_table(*table);
+ holder->set_index(Smi::FromInt(0));
+ holder->set_kind(Smi::FromInt(kind));
+ return isolate->heap()->undefined_value();
+}
+
+
+RUNTIME_FUNCTION(Runtime_SetIteratorNext) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
+ return *JSSetIterator::Next(holder);
+}
+
+
+RUNTIME_FUNCTION(Runtime_MapInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
- Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
+ Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
holder->set_table(*table);
return *holder;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
+RUNTIME_FUNCTION(Runtime_MapGet) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
- Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
- Handle<Object> lookup(table->Lookup(*key), isolate);
+ Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
+ Handle<Object> lookup(table->Lookup(key), isolate);
return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
+RUNTIME_FUNCTION(Runtime_MapHas) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
- Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
- Handle<Object> lookup(table->Lookup(*key), isolate);
+ Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
+ Handle<Object> lookup(table->Lookup(key), isolate);
return isolate->heap()->ToBoolean(!lookup->IsTheHole());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
+RUNTIME_FUNCTION(Runtime_MapDelete) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
- Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
- Handle<Object> lookup(table->Lookup(*key), isolate);
- Handle<ObjectHashTable> new_table =
- ObjectHashTable::Put(table, key, isolate->factory()->the_hole_value());
+ Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
+ bool was_present = false;
+ Handle<OrderedHashMap> new_table =
+ OrderedHashMap::Remove(table, key, &was_present);
holder->set_table(*new_table);
- return isolate->heap()->ToBoolean(!lookup->IsTheHole());
+ return isolate->heap()->ToBoolean(was_present);
+}
+
+
+RUNTIME_FUNCTION(Runtime_MapClear) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
+ Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
+ table = OrderedHashMap::Clear(table);
+ holder->set_table(*table);
+ return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
+RUNTIME_FUNCTION(Runtime_MapSet) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
- Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
- Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
+ Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
+ Handle<OrderedHashMap> new_table = OrderedHashMap::Put(table, key, value);
holder->set_table(*new_table);
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
+RUNTIME_FUNCTION(Runtime_MapGetSize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
- Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
+ Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
return Smi::FromInt(table->NumberOfElements());
}
-static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
+RUNTIME_FUNCTION(Runtime_MapIteratorInitialize) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 3);
+ CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSMap, map, 1);
+ CONVERT_SMI_ARG_CHECKED(kind, 2)
+ RUNTIME_ASSERT(kind == JSMapIterator::kKindKeys
+ || kind == JSMapIterator::kKindValues
+ || kind == JSMapIterator::kKindEntries);
+ Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
+ holder->set_table(*table);
+ holder->set_index(Smi::FromInt(0));
+ holder->set_kind(Smi::FromInt(kind));
+ return isolate->heap()->undefined_value();
+}
+
+
+RUNTIME_FUNCTION(Runtime_MapIteratorNext) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
+ return *JSMapIterator::Next(holder);
+}
+
+
+static Handle<JSWeakCollection> WeakCollectionInitialize(
+ Isolate* isolate,
Handle<JSWeakCollection> weak_collection) {
ASSERT(weak_collection->map()->inobject_properties() == 0);
- Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
+ Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0);
weak_collection->set_table(*table);
- weak_collection->set_next(Smi::FromInt(0));
- return *weak_collection;
+ return weak_collection;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
- return WeakCollectionInitialize(isolate, weak_collection);
+ return *WeakCollectionInitialize(isolate, weak_collection);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionGet) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+ RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
Handle<ObjectHashTable> table(
ObjectHashTable::cast(weak_collection->table()));
- Handle<Object> lookup(table->Lookup(*key), isolate);
+ RUNTIME_ASSERT(table->IsKey(*key));
+ Handle<Object> lookup(table->Lookup(key), isolate);
return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionHas) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+ RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
Handle<ObjectHashTable> table(
ObjectHashTable::cast(weak_collection->table()));
- Handle<Object> lookup(table->Lookup(*key), isolate);
+ RUNTIME_ASSERT(table->IsKey(*key));
+ Handle<Object> lookup(table->Lookup(key), isolate);
return isolate->heap()->ToBoolean(!lookup->IsTheHole());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+ RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
Handle<ObjectHashTable> table(ObjectHashTable::cast(
weak_collection->table()));
- Handle<Object> lookup(table->Lookup(*key), isolate);
+ RUNTIME_ASSERT(table->IsKey(*key));
+ bool was_present = false;
Handle<ObjectHashTable> new_table =
- ObjectHashTable::Put(table, key, isolate->factory()->the_hole_value());
+ ObjectHashTable::Remove(table, key, &was_present);
weak_collection->set_table(*new_table);
- return isolate->heap()->ToBoolean(!lookup->IsTheHole());
+ return isolate->heap()->ToBoolean(was_present);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
+RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
- Handle<Object> value(args[2], isolate);
+ RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
Handle<ObjectHashTable> table(
ObjectHashTable::cast(weak_collection->table()));
+ RUNTIME_ASSERT(table->IsKey(*key));
Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
weak_collection->set_table(*new_table);
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
+RUNTIME_FUNCTION(Runtime_ClassOf) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* obj = args[0];
+ CONVERT_ARG_CHECKED(Object, obj, 0);
if (!obj->IsJSObject()) return isolate->heap()->null_value();
return JSObject::cast(obj)->class_name();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
+RUNTIME_FUNCTION(Runtime_GetPrototype) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
@@ -1638,45 +1811,52 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
do {
if (obj->IsAccessCheckNeeded() &&
- !isolate->MayNamedAccessWrapper(Handle<JSObject>::cast(obj),
- isolate->factory()->proto_string(),
- v8::ACCESS_GET)) {
- isolate->ReportFailedAccessCheck(JSObject::cast(*obj), v8::ACCESS_GET);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ !isolate->MayNamedAccess(Handle<JSObject>::cast(obj),
+ isolate->factory()->proto_string(),
+ v8::ACCESS_GET)) {
+ isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(obj),
+ v8::ACCESS_GET);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->undefined_value();
}
- obj = handle(obj->GetPrototype(isolate), isolate);
+ obj = Object::GetPrototype(isolate, obj);
} while (obj->IsJSObject() &&
JSObject::cast(*obj)->map()->is_hidden_prototype());
return *obj;
}
-static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
- Object* receiver) {
- Object* current = receiver->GetPrototype(isolate);
+static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
+ Isolate* isolate, Handle<Object> receiver) {
+ Handle<Object> current = Object::GetPrototype(isolate, receiver);
while (current->IsJSObject() &&
- JSObject::cast(current)->map()->is_hidden_prototype()) {
- current = current->GetPrototype(isolate);
+ JSObject::cast(*current)->map()->is_hidden_prototype()) {
+ current = Object::GetPrototype(isolate, current);
}
return current;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
+RUNTIME_FUNCTION(Runtime_SetPrototype) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
- if (FLAG_harmony_observation && obj->map()->is_observed()) {
- Handle<Object> old_value(
- GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
-
- Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ if (obj->IsAccessCheckNeeded() &&
+ !isolate->MayNamedAccess(
+ obj, isolate->factory()->proto_string(), v8::ACCESS_SET)) {
+ isolate->ReportFailedAccessCheck(obj, v8::ACCESS_SET);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
+ return isolate->heap()->undefined_value();
+ }
+ if (obj->map()->is_observed()) {
+ Handle<Object> old_value = GetPrototypeSkipHiddenPrototypes(isolate, obj);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSObject::SetPrototype(obj, prototype, true));
- Handle<Object> new_value(
- GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
+ Handle<Object> new_value = GetPrototypeSkipHiddenPrototypes(isolate, obj);
if (!new_value->SameValue(*old_value)) {
JSObject::EnqueueChangeRecord(obj, "setPrototype",
isolate->factory()->proto_string(),
@@ -1684,22 +1864,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
}
return *result;
}
- Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSObject::SetPrototype(obj, prototype, true));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
+ HandleScope shs(isolate);
ASSERT(args.length() == 2);
// See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
- Object* O = args[0];
- Object* V = args[1];
+ CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
while (true) {
- Object* prototype = V->GetPrototype(isolate);
+ Handle<Object> prototype = Object::GetPrototype(isolate, V);
if (prototype->IsNull()) return isolate->heap()->false_value();
- if (O == prototype) return isolate->heap()->true_value();
+ if (*O == *prototype) return isolate->heap()->true_value();
V = prototype;
}
}
@@ -1708,6 +1890,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
static bool CheckAccessException(Object* callback,
v8::AccessType access_type) {
DisallowHeapAllocation no_gc;
+ ASSERT(!callback->IsForeign());
if (callback->IsAccessorInfo()) {
AccessorInfo* info = AccessorInfo::cast(callback);
return
@@ -1763,22 +1946,22 @@ static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
if (name->AsArrayIndex(&index)) {
// TODO(1095): we should traverse hidden prototype hierachy as well.
if (CheckGenericAccess(
- obj, obj, index, access_type, &Isolate::MayIndexedAccessWrapper)) {
+ obj, obj, index, access_type, &Isolate::MayIndexedAccess)) {
return ACCESS_ALLOWED;
}
- obj->GetIsolate()->ReportFailedAccessCheck(*obj, access_type);
+ obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
return ACCESS_FORBIDDEN;
}
Isolate* isolate = obj->GetIsolate();
LookupResult lookup(isolate);
- obj->LocalLookup(*name, &lookup, true);
+ obj->LookupOwn(name, &lookup, true);
if (!lookup.IsProperty()) return ACCESS_ABSENT;
Handle<JSObject> holder(lookup.holder(), isolate);
if (CheckGenericAccess<Handle<Object> >(
- obj, holder, name, access_type, &Isolate::MayNamedAccessWrapper)) {
+ obj, holder, name, access_type, &Isolate::MayNamedAccess)) {
return ACCESS_ALLOWED;
}
@@ -1795,7 +1978,7 @@ static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
case INTERCEPTOR:
// If the object has an interceptor, try real named properties.
// Overwrite the result to fetch the correct property later.
- holder->LookupRealNamedProperty(*name, &lookup);
+ holder->LookupRealNamedProperty(name, &lookup);
if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
return ACCESS_ALLOWED;
@@ -1806,7 +1989,7 @@ static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
break;
}
- isolate->ReportFailedAccessCheck(*obj, access_type);
+ isolate->ReportFailedAccessCheck(obj, access_type);
return ACCESS_FORBIDDEN;
}
@@ -1824,40 +2007,43 @@ enum PropertyDescriptorIndices {
};
-static Handle<Object> GetOwnProperty(Isolate* isolate,
- Handle<JSObject> obj,
- Handle<Name> name) {
+MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
+ Handle<JSObject> obj,
+ Handle<Name> name) {
Heap* heap = isolate->heap();
Factory* factory = isolate->factory();
// Due to some WebKit tests, we want to make sure that we do not log
// more than one access failure here.
AccessCheckResult access_check_result =
CheckPropertyAccess(obj, name, v8::ACCESS_HAS);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
switch (access_check_result) {
case ACCESS_FORBIDDEN: return factory->false_value();
case ACCESS_ALLOWED: break;
case ACCESS_ABSENT: return factory->undefined_value();
}
- PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name);
+ PropertyAttributes attrs = JSReceiver::GetOwnPropertyAttributes(obj, name);
if (attrs == ABSENT) {
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return factory->undefined_value();
}
ASSERT(!isolate->has_scheduled_exception());
- AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name);
- Handle<AccessorPair> accessors(raw_accessors, isolate);
+ Handle<AccessorPair> accessors;
+ bool has_accessors =
+ JSObject::GetOwnPropertyAccessorPair(obj, name).ToHandle(&accessors);
Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
- elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL));
+ elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(has_accessors));
- if (raw_accessors == NULL) {
+ if (!has_accessors) {
elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
- // GetProperty does access check.
- Handle<Object> value = GetProperty(isolate, obj, name);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<Object>::null());
+ // Runtime::GetObjectProperty does access check.
+ Handle<Object> value;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value, Runtime::GetObjectProperty(isolate, obj, name),
+ Object);
elms->set(VALUE_INDEX, *value);
} else {
// Access checks are performed for both accessors separately.
@@ -1869,14 +2055,14 @@ static Handle<Object> GetOwnProperty(Isolate* isolate,
ASSERT(!isolate->has_scheduled_exception());
elms->set(GETTER_INDEX, *getter);
} else {
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
}
if (!setter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_SET)) {
ASSERT(!isolate->has_scheduled_exception());
elms->set(SETTER_INDEX, *setter);
} else {
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
}
}
@@ -1891,28 +2077,30 @@ static Handle<Object> GetOwnProperty(Isolate* isolate,
// [false, value, Writeable, Enumerable, Configurable]
// if args[1] is an accessor on args[0]
// [true, GetFunction, SetFunction, Enumerable, Configurable]
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
+RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
- Handle<Object> result = GetOwnProperty(isolate, obj, name);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, GetOwnProperty(isolate, obj, name));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
+RUNTIME_FUNCTION(Runtime_PreventExtensions) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
- Handle<Object> result = JSObject::PreventExtensions(obj);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, JSObject::PreventExtensions(obj));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
+RUNTIME_FUNCTION(Runtime_IsExtensible) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSObject, obj, 0);
@@ -1926,44 +2114,46 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
+RUNTIME_FUNCTION(Runtime_RegExpCompile) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
- Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, RegExpImpl::Compile(re, pattern, flags));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
+RUNTIME_FUNCTION(Runtime_CreateApiFunction) {
HandleScope scope(isolate);
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
- return *isolate->factory()->CreateApiFunction(data);
+ CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
+ return *isolate->factory()->CreateApiFunction(data, prototype);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
+RUNTIME_FUNCTION(Runtime_IsTemplate) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* arg = args[0];
+ CONVERT_ARG_HANDLE_CHECKED(Object, arg, 0);
bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
return isolate->heap()->ToBoolean(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
+RUNTIME_FUNCTION(Runtime_GetTemplateField) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(HeapObject, templ, 0);
- CONVERT_SMI_ARG_CHECKED(index, 1)
+ CONVERT_SMI_ARG_CHECKED(index, 1);
int offset = index * kPointerSize + HeapObject::kHeaderSize;
InstanceType type = templ->map()->instance_type();
- RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
- type == OBJECT_TEMPLATE_INFO_TYPE);
+ RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
+ type == OBJECT_TEMPLATE_INFO_TYPE);
RUNTIME_ASSERT(offset > 0);
if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
@@ -1974,38 +2164,40 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(HeapObject, object, 0);
- Map* old_map = object->map();
+ CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
+ Handle<Map> old_map(object->map());
bool needs_access_checks = old_map->is_access_check_needed();
if (needs_access_checks) {
// Copy map so it won't interfere constructor's initial map.
- Map* new_map;
- MaybeObject* maybe_new_map = old_map->Copy();
- if (!maybe_new_map->To(&new_map)) return maybe_new_map;
-
+ Handle<Map> new_map = Map::Copy(old_map);
new_map->set_is_access_check_needed(false);
- object->set_map(new_map);
+ if (object->IsJSObject()) {
+ JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
+ } else {
+ object->set_map(*new_map);
+ }
}
return isolate->heap()->ToBoolean(needs_access_checks);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(HeapObject, object, 0);
- Map* old_map = object->map();
+ CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
+ Handle<Map> old_map(object->map());
if (!old_map->is_access_check_needed()) {
// Copy map so it won't interfere constructor's initial map.
- Map* new_map;
- MaybeObject* maybe_new_map = old_map->Copy();
- if (!maybe_new_map->To(&new_map)) return maybe_new_map;
-
+ Handle<Map> new_map = Map::Copy(old_map);
new_map->set_is_access_check_needed(true);
- object->set_map(new_map);
+ if (object->IsJSObject()) {
+ JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
+ } else {
+ object->set_map(*new_map);
+ }
}
return isolate->heap()->undefined_value();
}
@@ -2021,7 +2213,7 @@ static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
+RUNTIME_FUNCTION(Runtime_SetAccessorProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 6);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -2030,6 +2222,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
CONVERT_SMI_ARG_CHECKED(attribute, 4);
CONVERT_SMI_ARG_CHECKED(access_control, 5);
+ RUNTIME_ASSERT(getter->IsUndefined() || getter->IsFunctionTemplateInfo());
+ RUNTIME_ASSERT(setter->IsUndefined() || setter->IsFunctionTemplateInfo());
+ RUNTIME_ASSERT(PropertyDetails::AttributesField::is_valid(
+ static_cast<PropertyAttributes>(attribute)));
JSObject::DefineAccessor(object,
name,
InstantiateAccessorComponent(isolate, getter),
@@ -2040,26 +2236,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
}
-static Failure* ThrowRedeclarationError(Isolate* isolate,
- const char* type,
- Handle<String> name) {
+static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
HandleScope scope(isolate);
- Handle<Object> type_handle =
- isolate->factory()->NewStringFromAscii(CStrVector(type));
- Handle<Object> args[2] = { type_handle, name };
- Handle<Object> error =
- isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
+ Handle<Object> args[1] = { name };
+ Handle<Object> error = isolate->factory()->NewTypeError(
+ "var_redeclaration", HandleVector(args, 1));
return isolate->Throw(*error);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
+RUNTIME_FUNCTION(RuntimeHidden_DeclareGlobals) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
Handle<GlobalObject> global = Handle<GlobalObject>(
isolate->context()->global_object());
- Handle<Context> context = args.at<Context>(0);
+ CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
CONVERT_SMI_ARG_CHECKED(flags, 2);
@@ -2081,19 +2273,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
if (is_var || is_const) {
// Lookup the property in the global object, and don't set the
// value of the variable if the property is already there.
- // Do the lookup locally only, see ES5 erratum.
+ // Do the lookup own properties only, see ES5 erratum.
LookupResult lookup(isolate);
- if (FLAG_es52_globals) {
- global->LocalLookup(*name, &lookup, true);
- } else {
- global->Lookup(*name, &lookup);
- }
+ global->LookupOwn(name, &lookup, true);
if (lookup.IsFound()) {
// We found an existing property. Unless it was an interceptor
// that claims the property is absent, skip this declaration.
if (!lookup.IsInterceptor()) continue;
- PropertyAttributes attributes = global->GetPropertyAttribute(*name);
- if (attributes != ABSENT) continue;
+ if (JSReceiver::GetPropertyAttributes(global, name) != ABSENT) continue;
// Fall-through and introduce the absent property by using
// SetProperty.
}
@@ -2108,7 +2295,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
}
LookupResult lookup(isolate);
- global->LocalLookup(*name, &lookup, true);
+ global->LookupOwn(name, &lookup, true);
// Compute the property attributes. According to ECMA-262,
// the property must be non-configurable except in eval.
@@ -2122,29 +2309,30 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
attr |= READ_ONLY;
}
- LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
+ StrictMode strict_mode = DeclareGlobalsStrictMode::decode(flags);
if (!lookup.IsFound() || is_function) {
- // If the local property exists, check that we can reconfigure it
+ // If the own property exists, check that we can reconfigure it
// as required for function declarations.
if (lookup.IsFound() && lookup.IsDontDelete()) {
if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
lookup.IsPropertyCallbacks()) {
- return ThrowRedeclarationError(isolate, "function", name);
+ return ThrowRedeclarationError(isolate, name);
}
// If the existing property is not configurable, keep its attributes.
attr = lookup.GetAttributes();
}
// Define or redefine own property.
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(
global, name, value, static_cast<PropertyAttributes>(attr)));
} else {
// Do a [[Put]] on the existing (own) property.
- RETURN_IF_EMPTY_HANDLE(isolate,
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate,
JSObject::SetProperty(
global, name, value, static_cast<PropertyAttributes>(attr),
- language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
+ strict_mode));
}
}
@@ -2153,20 +2341,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
+RUNTIME_FUNCTION(RuntimeHidden_DeclareContextSlot) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
// Declarations are always made in a function or native context. 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.
- RUNTIME_ASSERT(args[0]->IsContext());
- Handle<Context> context(Context::cast(args[0])->declaration_context());
-
- Handle<String> name(String::cast(args[1]));
- PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
+ 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(mode_arg, 2);
+ PropertyAttributes mode = static_cast<PropertyAttributes>(mode_arg);
RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
- Handle<Object> initial_value(args[3], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3);
int index;
PropertyAttributes attributes;
@@ -2182,8 +2370,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
// Functions are not read-only.
ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
- const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
- return ThrowRedeclarationError(isolate, type, name);
+ return ThrowRedeclarationError(isolate, name);
}
// Initialize it if necessary.
@@ -2198,10 +2385,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
// Slow case: The property is in the context extension object of a
// function context or the global object of a native context.
Handle<JSObject> object = Handle<JSObject>::cast(holder);
- RETURN_IF_EMPTY_HANDLE(
+ RETURN_FAILURE_ON_EXCEPTION(
isolate,
- JSReceiver::SetProperty(object, name, initial_value, mode,
- kNonStrictMode));
+ JSReceiver::SetProperty(object, name, initial_value, mode, SLOPPY));
}
}
@@ -2224,7 +2410,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
// Declare the property by setting it to the initial value if provided,
// or undefined, and use the correct mode (e.g. READ_ONLY attribute for
// constant declarations).
- ASSERT(!JSReceiver::HasLocalProperty(object, name));
+ ASSERT(!JSReceiver::HasOwnProperty(object, name));
Handle<Object> value(isolate->heap()->undefined_value(), isolate);
if (*initial_value != NULL) value = initial_value;
// Declaring a const context slot is a conflicting declaration if
@@ -2236,18 +2422,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
if (initial_value->IsTheHole() &&
!object->IsJSContextExtensionObject()) {
LookupResult lookup(isolate);
- object->Lookup(*name, &lookup);
+ object->Lookup(name, &lookup);
if (lookup.IsPropertyCallbacks()) {
- return ThrowRedeclarationError(isolate, "const", name);
+ return ThrowRedeclarationError(isolate, name);
}
}
if (object->IsJSGlobalObject()) {
// Define own property on the global object.
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, mode));
} else {
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSReceiver::SetProperty(object, name, value, mode, SLOPPY));
}
}
@@ -2255,7 +2441,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
+RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
HandleScope scope(isolate);
// args[0] == name
// args[1] == language_mode
@@ -2267,35 +2453,34 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
bool assign = args.length() == 3;
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
- RUNTIME_ASSERT(args[1]->IsSmi());
- CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
- StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
- ? kNonStrictMode : kStrictMode;
+ CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
// According to ECMA-262, section 12.2, page 62, the property must
// not be deletable.
PropertyAttributes attributes = DONT_DELETE;
- // Lookup the property locally in the global object. If it isn't
+ // Lookup the property as own on the global object. If it isn't
// there, there is a property with this name in the prototype chain.
// We follow Safari and Firefox behavior and only set the property
- // locally if there is an explicit initialization value that we have
+ // if there is an explicit initialization value that we have
// to assign to the property.
// Note that objects can have hidden prototypes, so we need to traverse
- // the whole chain of hidden prototypes to do a 'local' lookup.
+ // the whole chain of hidden prototypes to do an 'own' lookup.
LookupResult lookup(isolate);
- isolate->context()->global_object()->LocalLookup(*name, &lookup, true);
+ isolate->context()->global_object()->LookupOwn(name, &lookup, true);
if (lookup.IsInterceptor()) {
+ Handle<JSObject> holder(lookup.holder());
PropertyAttributes intercepted =
- lookup.holder()->GetPropertyAttribute(*name);
+ JSReceiver::GetPropertyAttributes(holder, name);
if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
// Found an interceptor that's not read only.
if (assign) {
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
- Handle<Object> result = JSObject::SetPropertyForResult(
- handle(lookup.holder()), &lookup, name, value, attributes,
- strict_mode_flag);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSObject::SetPropertyForResult(
+ holder, &lookup, name, value, attributes, strict_mode));
return *result;
} else {
return isolate->heap()->undefined_value();
@@ -2306,23 +2491,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
if (assign) {
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
Handle<GlobalObject> global(isolate->context()->global_object());
- Handle<Object> result = JSReceiver::SetProperty(
- global, name, value, attributes, strict_mode_flag);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSReceiver::SetProperty(global, name, value, attributes, strict_mode));
return *result;
}
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
+RUNTIME_FUNCTION(RuntimeHidden_InitializeConstGlobal) {
SealHandleScope shs(isolate);
// All constants are declared with an initial value. The name
// of the constant is the first argument and the initial value
// is the second.
RUNTIME_ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
- Handle<Object> value = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
// Get the current global object from top.
GlobalObject* global = isolate->context()->global_object();
@@ -2332,20 +2518,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
PropertyAttributes attributes =
static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
- // Lookup the property locally in the global object. If it isn't
+ // Lookup the property as own on the global object. If it isn't
// there, we add the property and take special precautions to always
- // add it as a local property even in case of callbacks in the
- // prototype chain (this rules out using SetProperty).
- // We use SetLocalPropertyIgnoreAttributes instead
+ // add it even in case of callbacks in the prototype chain (this rules
+ // out using SetProperty). We use SetOwnPropertyIgnoreAttributes instead
LookupResult lookup(isolate);
- global->LocalLookup(*name, &lookup);
+ global->LookupOwn(name, &lookup);
if (!lookup.IsFound()) {
HandleScope handle_scope(isolate);
Handle<GlobalObject> global(isolate->context()->global_object());
- RETURN_IF_EMPTY_HANDLE(
+ RETURN_FAILURE_ON_EXCEPTION(
isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
- attributes));
+ JSObject::SetOwnPropertyIgnoreAttributes(global, name, value,
+ attributes));
return *value;
}
@@ -2358,11 +2543,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
// BUG 1213575: Handle the case where we have to set a read-only
// property through an interceptor and only do it if it's
// uninitialized, e.g. the hole. Nirk...
- // Passing non-strict mode because the property is writable.
- RETURN_IF_EMPTY_HANDLE(
+ // Passing sloppy mode because the property is writable.
+ RETURN_FAILURE_ON_EXCEPTION(
isolate,
- JSReceiver::SetProperty(global, name, value, attributes,
- kNonStrictMode));
+ JSReceiver::SetProperty(global, name, value, attributes, SLOPPY));
return *value;
}
@@ -2372,7 +2556,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
// Strict mode handling not needed (const is disallowed in strict mode).
if (lookup.IsField()) {
FixedArray* properties = global->properties();
- int index = lookup.GetFieldIndex().field_index();
+ int index = lookup.GetFieldIndex().outobject_array_index();
if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
properties->set(index, *value);
}
@@ -2393,18 +2577,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
+RUNTIME_FUNCTION(RuntimeHidden_InitializeConstContextSlot) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- Handle<Object> value(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
ASSERT(!value->IsTheHole());
-
// Initializations are always done in a function or native context.
- RUNTIME_ASSERT(args[1]->IsContext());
- Handle<Context> context(Context::cast(args[1])->declaration_context());
-
- Handle<String> name(String::cast(args[2]));
+ CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
+ Handle<Context> context(context_arg->declaration_context());
+ CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
int index;
PropertyAttributes attributes;
@@ -2430,9 +2612,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
Handle<JSObject> global = Handle<JSObject>(
isolate->context()->global_object());
// Strict mode not needed (const disallowed in strict mode).
- RETURN_IF_EMPTY_HANDLE(
+ RETURN_FAILURE_ON_EXCEPTION(
isolate,
- JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
+ JSReceiver::SetProperty(global, name, value, NONE, SLOPPY));
return *value;
}
@@ -2457,15 +2639,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
// Set it if it hasn't been set before. NOTE: We cannot use
// GetProperty() to get the current value as it 'unholes' the value.
LookupResult lookup(isolate);
- object->LocalLookupRealNamedProperty(*name, &lookup);
+ object->LookupOwnRealNamedProperty(name, &lookup);
ASSERT(lookup.IsFound()); // the property was declared
ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
if (lookup.IsField()) {
FixedArray* properties = object->properties();
- int index = lookup.GetFieldIndex().field_index();
- if (properties->get(index)->IsTheHole()) {
- properties->set(index, *value);
+ FieldIndex index = lookup.GetFieldIndex();
+ ASSERT(!index.is_inobject());
+ if (properties->get(index.outobject_array_index())->IsTheHole()) {
+ properties->set(index.outobject_array_index(), *value);
}
} else if (lookup.IsNormal()) {
if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
@@ -2481,10 +2664,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
// read-only property.
if ((attributes & READ_ONLY) == 0) {
// Strict mode not needed (const disallowed in strict mode).
- RETURN_IF_EMPTY_HANDLE(
+ RETURN_FAILURE_ON_EXCEPTION(
isolate,
- JSReceiver::SetProperty(object, name, value, attributes,
- kNonStrictMode));
+ JSReceiver::SetProperty(object, name, value, attributes, SLOPPY));
}
}
@@ -2492,20 +2674,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
}
-RUNTIME_FUNCTION(MaybeObject*,
- Runtime_OptimizeObjectForAddingMultipleProperties) {
+RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_SMI_ARG_CHECKED(properties, 1);
- if (object->HasFastProperties()) {
+ // Conservative upper limit to prevent fuzz tests from going OOM.
+ RUNTIME_ASSERT(properties <= 100000);
+ if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
}
return *object;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
+RUNTIME_FUNCTION(RuntimeHidden_RegExpExec) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
@@ -2517,54 +2700,37 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
RUNTIME_ASSERT(index >= 0);
RUNTIME_ASSERT(index <= subject->length());
isolate->counters()->regexp_entry_runtime()->Increment();
- Handle<Object> result = RegExpImpl::Exec(regexp,
- subject,
- index,
- last_match_info);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ RegExpImpl::Exec(regexp, subject, index, last_match_info));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_RegExpConstructResult) {
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 3);
- CONVERT_SMI_ARG_CHECKED(elements_count, 0);
- if (elements_count < 0 ||
- elements_count > FixedArray::kMaxLength ||
- !Smi::IsValid(elements_count)) {
- return isolate->ThrowIllegalOperation();
- }
- Object* new_object;
- { MaybeObject* maybe_new_object =
- isolate->heap()->AllocateFixedArray(elements_count);
- if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
- }
- FixedArray* elements = FixedArray::cast(new_object);
- { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
- JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
- if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
- }
- {
- DisallowHeapAllocation no_gc;
- HandleScope scope(isolate);
- reinterpret_cast<HeapObject*>(new_object)->
- set_map(isolate->native_context()->regexp_result_map());
- }
- JSArray* array = JSArray::cast(new_object);
- array->set_properties(isolate->heap()->empty_fixed_array());
- array->set_elements(elements);
- array->set_length(Smi::FromInt(elements_count));
+ CONVERT_SMI_ARG_CHECKED(size, 0);
+ RUNTIME_ASSERT(size >= 0 && size <= FixedArray::kMaxLength);
+ CONVERT_ARG_HANDLE_CHECKED(Object, index, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, input, 2);
+ Handle<FixedArray> elements = isolate->factory()->NewFixedArray(size);
+ Handle<Map> regexp_map(isolate->native_context()->regexp_result_map());
+ Handle<JSObject> object =
+ isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED, false);
+ Handle<JSArray> array = Handle<JSArray>::cast(object);
+ array->set_elements(*elements);
+ array->set_length(Smi::FromInt(size));
// Write in-object properties after the length of the array.
- array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
- array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
- return array;
+ array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, *index);
+ array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, *input);
+ return *array;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
+RUNTIME_FUNCTION(Runtime_RegExpInitializeObject) {
HandleScope scope(isolate);
- DisallowHeapAllocation no_allocation;
ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
@@ -2607,24 +2773,27 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
Handle<Object> zero(Smi::FromInt(0), isolate);
Factory* factory = isolate->factory();
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->source_string(), source, final));
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->global_string(), global, final));
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->ignore_case_string(), ignoreCase, final));
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->multiline_string(), multiline, final));
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
- regexp, factory->last_index_string(), zero, writable));
+ JSObject::SetOwnPropertyIgnoreAttributes(
+ regexp, factory->source_string(), source, final).Check();
+ JSObject::SetOwnPropertyIgnoreAttributes(
+ regexp, factory->global_string(), global, final).Check();
+ JSObject::SetOwnPropertyIgnoreAttributes(
+ regexp, factory->ignore_case_string(), ignoreCase, final).Check();
+ JSObject::SetOwnPropertyIgnoreAttributes(
+ regexp, factory->multiline_string(), multiline, final).Check();
+ JSObject::SetOwnPropertyIgnoreAttributes(
+ regexp, factory->last_index_string(), zero, writable).Check();
return *regexp;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
+RUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
+ Object* length = prototype->length();
+ RUNTIME_ASSERT(length->IsSmi() && Smi::cast(length)->value() == 0);
+ RUNTIME_ASSERT(prototype->HasFastSmiOrObjectElements());
// This is necessary to enable fast checks for absence of elements
// on Array.prototype and below.
prototype->set_elements(isolate->heap()->empty_fixed_array());
@@ -2632,28 +2801,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
}
-static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
- Handle<JSObject> holder,
- const char* name,
- Builtins::Name builtin_name) {
+static void InstallBuiltin(Isolate* isolate,
+ Handle<JSObject> holder,
+ const char* name,
+ Builtins::Name builtin_name) {
Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
Handle<Code> code(isolate->builtins()->builtin(builtin_name));
Handle<JSFunction> optimized =
- isolate->factory()->NewFunction(key,
- JS_OBJECT_TYPE,
- JSObject::kHeaderSize,
- code,
- false);
+ isolate->factory()->NewFunctionWithoutPrototype(key, code);
optimized->shared()->DontAdaptArguments();
- JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
- return optimized;
+ JSReceiver::SetProperty(holder, key, optimized, NONE, STRICT).Assert();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
+RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) {
HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
+ ASSERT(args.length() == 0);
+ Handle<JSObject> holder =
+ isolate->factory()->NewJSObject(isolate->object_function());
InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
@@ -2667,49 +2832,43 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsCallable) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(Object, obj, 0);
- return isolate->heap()->ToBoolean(obj->IsCallable());
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsClassicModeFunction) {
+RUNTIME_FUNCTION(Runtime_IsSloppyModeFunction) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
if (!callable->IsJSFunction()) {
HandleScope scope(isolate);
- bool threw = false;
- Handle<Object> delegate = Execution::TryGetFunctionDelegate(
- isolate, Handle<JSReceiver>(callable), &threw);
- if (threw) return Failure::Exception();
+ Handle<Object> delegate;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, delegate,
+ Execution::TryGetFunctionDelegate(
+ isolate, Handle<JSReceiver>(callable)));
callable = JSFunction::cast(*delegate);
}
JSFunction* function = JSFunction::cast(callable);
SharedFunctionInfo* shared = function->shared();
- return isolate->heap()->ToBoolean(shared->is_classic_mode());
+ return isolate->heap()->ToBoolean(shared->strict_mode() == SLOPPY);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
+RUNTIME_FUNCTION(Runtime_GetDefaultReceiver) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
if (!callable->IsJSFunction()) {
HandleScope scope(isolate);
- bool threw = false;
- Handle<Object> delegate = Execution::TryGetFunctionDelegate(
- isolate, Handle<JSReceiver>(callable), &threw);
- if (threw) return Failure::Exception();
+ Handle<Object> delegate;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, delegate,
+ Execution::TryGetFunctionDelegate(
+ isolate, Handle<JSReceiver>(callable)));
callable = JSFunction::cast(*delegate);
}
JSFunction* function = JSFunction::cast(callable);
SharedFunctionInfo* shared = function->shared();
- if (shared->native() || !shared->is_classic_mode()) {
+ if (shared->native() || shared->strict_mode() == STRICT) {
return isolate->heap()->undefined_value();
}
// Returns undefined for strict or native functions, or
@@ -2721,13 +2880,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
+RUNTIME_FUNCTION(RuntimeHidden_MaterializeRegExpLiteral) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
- int index = args.smi_at(1);
- Handle<String> pattern = args.at<String>(2);
- Handle<String> flags = args.at<String>(3);
+ CONVERT_SMI_ARG_CHECKED(index, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
+ CONVERT_ARG_HANDLE_CHECKED(String, flags, 3);
// Get the RegExp function from the context in the literals array.
// This is the RegExp function from the context in which the
@@ -2738,20 +2897,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
Handle<JSFunction>(
JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
// Compute the regular expression literal.
- bool has_pending_exception;
- Handle<Object> regexp =
- RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
- &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<Object> regexp;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, regexp,
+ RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags));
literals->set(index, *regexp);
return *regexp;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
+RUNTIME_FUNCTION(Runtime_FunctionGetName) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -2760,7 +2915,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
+RUNTIME_FUNCTION(Runtime_FunctionSetName) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -2771,7 +2926,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
+RUNTIME_FUNCTION(Runtime_FunctionNameShouldPrintAsAnonymous) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0);
@@ -2780,7 +2935,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
+RUNTIME_FUNCTION(Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0);
@@ -2789,7 +2944,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
+RUNTIME_FUNCTION(Runtime_FunctionIsGenerator) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0);
@@ -2797,18 +2952,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
+RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0);
- f->RemovePrototype();
+ RUNTIME_ASSERT(f->RemovePrototype());
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
+RUNTIME_FUNCTION(Runtime_FunctionGetScript) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -2816,11 +2971,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
if (!script->IsScript()) return isolate->heap()->undefined_value();
- return *GetScriptWrapper(Handle<Script>::cast(script));
+ return *Script::GetWrapper(Handle<Script>::cast(script));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
+RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -2830,7 +2985,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
+RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -2840,7 +2995,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
+RUNTIME_FUNCTION(Runtime_FunctionGetPositionForOffset) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -2854,7 +3009,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
+RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -2865,72 +3020,32 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
+RUNTIME_FUNCTION(Runtime_FunctionSetLength) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(JSFunction, fun, 0);
CONVERT_SMI_ARG_CHECKED(length, 1);
+ RUNTIME_ASSERT((length & 0xC0000000) == 0xC0000000 ||
+ (length & 0xC0000000) == 0x0);
fun->shared()->set_length(length);
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
+RUNTIME_FUNCTION(Runtime_FunctionSetPrototype) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
- ASSERT(fun->should_have_prototype());
+ RUNTIME_ASSERT(fun->should_have_prototype());
Accessors::FunctionSetPrototype(fun, value);
return args[0]; // return TOS
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
- SealHandleScope shs(isolate);
- RUNTIME_ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(JSFunction, function, 0);
-
- String* name = isolate->heap()->prototype_string();
-
- if (function->HasFastProperties()) {
- // Construct a new field descriptor with updated attributes.
- DescriptorArray* instance_desc = function->map()->instance_descriptors();
-
- int index = instance_desc->SearchWithCache(name, function->map());
- ASSERT(index != DescriptorArray::kNotFound);
- PropertyDetails details = instance_desc->GetDetails(index);
-
- CallbacksDescriptor new_desc(name,
- instance_desc->GetValue(index),
- static_cast<PropertyAttributes>(details.attributes() | READ_ONLY));
-
- // Create a new map featuring the new field descriptors array.
- Map* new_map;
- MaybeObject* maybe_map =
- function->map()->CopyReplaceDescriptor(
- instance_desc, &new_desc, index, OMIT_TRANSITION);
- if (!maybe_map->To(&new_map)) return maybe_map;
-
- function->set_map(new_map);
- } else { // Dictionary properties.
- // Directly manipulate the property details.
- int entry = function->property_dictionary()->FindEntry(name);
- ASSERT(entry != NameDictionary::kNotFound);
- PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
- PropertyDetails new_details(
- static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
- details.type(),
- details.dictionary_index());
- function->property_dictionary()->DetailsAtPut(entry, new_details);
- }
- return function;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
+RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -2939,7 +3054,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
+RUNTIME_FUNCTION(Runtime_FunctionIsBuiltin) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -2948,21 +3063,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
+RUNTIME_FUNCTION(Runtime_SetCode) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
- Handle<Object> code = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1);
- if (code->IsNull()) return *target;
- RUNTIME_ASSERT(code->IsJSFunction());
- Handle<JSFunction> source = Handle<JSFunction>::cast(code);
Handle<SharedFunctionInfo> target_shared(target->shared());
Handle<SharedFunctionInfo> source_shared(source->shared());
+ RUNTIME_ASSERT(!source_shared->bound());
- if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) {
- return Failure::Exception();
+ if (!Compiler::EnsureCompiled(source, KEEP_EXCEPTION)) {
+ return isolate->heap()->exception();
}
// Mark both, the source and the target, as un-flushable because the
@@ -2977,6 +3090,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
target_shared->ReplaceCode(source_shared->code());
target_shared->set_scope_info(source_shared->scope_info());
target_shared->set_length(source_shared->length());
+ target_shared->set_feedback_vector(source_shared->feedback_vector());
target_shared->set_formal_parameter_count(
source_shared->formal_parameter_count());
target_shared->set_script(source_shared->script());
@@ -2986,6 +3100,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
bool was_native = target_shared->native();
target_shared->set_compiler_hints(source_shared->compiler_hints());
target_shared->set_native(was_native);
+ target_shared->set_profiler_ticks(source_shared->profiler_ticks());
// Set the code of the target function.
target->ReplaceCode(source_shared->code());
@@ -3014,32 +3129,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 2);
- CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
- CONVERT_SMI_ARG_CHECKED(num, 1);
- RUNTIME_ASSERT(num >= 0);
- // If objects constructed from this function exist then changing
- // 'estimated_nof_properties' is dangerous since the previous value might
- // have been compiled into the fast construct stub. Moreover, the inobject
- // slack tracking logic might have adjusted the previous value, so even
- // passing the same value is risky.
- if (!func->shared()->live_objects_may_exist()) {
- func->shared()->set_expected_nof_properties(num);
- if (func->has_initial_map()) {
- Handle<Map> new_initial_map =
- func->GetIsolate()->factory()->CopyMap(
- Handle<Map>(func->initial_map()));
- new_initial_map->set_unused_property_fields(num);
- func->set_initial_map(*new_initial_map);
- }
- }
- return isolate->heap()->undefined_value();
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) {
+RUNTIME_FUNCTION(RuntimeHidden_CreateJSGeneratorObject) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
@@ -3065,10 +3155,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_SuspendJSGeneratorObject) {
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0);
JavaScriptFrameIterator stack_iterator(isolate);
JavaScriptFrame* frame = stack_iterator.frame();
@@ -3097,11 +3187,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
ASSERT(!frame->HasHandler());
} else {
int stack_handler_index = -1;
- MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
- FixedArray* operand_stack;
- if (!alloc->To(&operand_stack)) return alloc;
- frame->SaveOperandStack(operand_stack, &stack_handler_index);
- generator_object->set_operand_stack(operand_stack);
+ Handle<FixedArray> operand_stack =
+ isolate->factory()->NewFixedArray(operands_count);
+ frame->SaveOperandStack(*operand_stack, &stack_handler_index);
+ generator_object->set_operand_stack(*operand_stack);
generator_object->set_stack_handler_index(stack_handler_index);
}
@@ -3116,7 +3205,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
// inlined into GeneratorNext and GeneratorThrow. EmitGeneratorResumeResume is
// called in any case, as it needs to reconstruct the stack frame and make space
// for arguments and operands.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
+RUNTIME_FUNCTION(RuntimeHidden_ResumeJSGeneratorObject) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
@@ -3128,13 +3217,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
ASSERT_EQ(frame->function(), generator_object->function());
ASSERT(frame->function()->is_compiled());
- STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
- STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
+ STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
+ STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
Address pc = generator_object->function()->code()->instruction_start();
int offset = generator_object->continuation();
ASSERT(offset > 0);
frame->set_pc(pc + offset);
+ if (FLAG_enable_ool_constant_pool) {
+ frame->set_constant_pool(
+ generator_object->function()->code()->constant_pool());
+ }
generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
FixedArray* operand_stack = generator_object->operand_stack();
@@ -3160,7 +3253,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) {
+RUNTIME_FUNCTION(RuntimeHidden_ThrowGeneratorStateError) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
@@ -3173,41 +3266,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
+RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
- Handle<Object> result = JSObject::Freeze(object);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
- return *result;
-}
+ // %ObjectFreeze is a fast path and these cases are handled elsewhere.
+ RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
+ !object->map()->is_observed() &&
+ !object->IsJSProxy());
-MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
- Object* char_code) {
- if (char_code->IsNumber()) {
- return isolate->heap()->LookupSingleCharacterStringFromCode(
- NumberToUint32(char_code) & 0xffff);
- }
- return isolate->heap()->empty_string();
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_StringCharCodeAt) {
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(String, subject, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
// Flatten the string. If someone wants to get a char at an index
// in a cons string, it is likely that more indices will be
// accessed.
- Object* flat;
- { MaybeObject* maybe_flat = subject->TryFlatten();
- if (!maybe_flat->ToObject(&flat)) return maybe_flat;
- }
- subject = String::cast(flat);
+ subject = String::Flatten(subject);
if (i >= static_cast<uint32_t>(subject->length())) {
return isolate->heap()->nan_value();
@@ -3217,10 +3302,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_CharFromCode) {
+ HandleScope handlescope(isolate);
ASSERT(args.length() == 1);
- return CharFromCode(isolate, args[0]);
+ if (args[0]->IsNumber()) {
+ CONVERT_NUMBER_CHECKED(uint32_t, code, Uint32, args[0]);
+ code &= 0xffff;
+ return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
+ }
+ return isolate->heap()->empty_string();
}
@@ -3293,8 +3383,7 @@ class FixedArrayBuilder {
}
Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
- Factory* factory = target_array->GetIsolate()->factory();
- factory->SetContent(target_array, array_);
+ JSArray::SetContent(target_array, array_);
target_array->set_length(Smi::FromInt(length_));
return target_array;
}
@@ -3381,14 +3470,20 @@ class ReplacementStringBuilder {
}
- Handle<String> ToString() {
+ MaybeHandle<String> ToString() {
+ Isolate* isolate = heap_->isolate();
if (array_builder_.length() == 0) {
- return heap_->isolate()->factory()->empty_string();
+ return isolate->factory()->empty_string();
}
Handle<String> joined_string;
if (is_ascii_) {
- Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
+ Handle<SeqOneByteString> seq;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, seq,
+ isolate->factory()->NewRawOneByteString(character_count_),
+ String);
+
DisallowHeapAllocation no_gc;
uint8_t* char_buffer = seq->GetChars();
StringBuilderConcatHelper(*subject_,
@@ -3398,7 +3493,12 @@ class ReplacementStringBuilder {
joined_string = Handle<String>::cast(seq);
} else {
// Non-ASCII.
- Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
+ Handle<SeqTwoByteString> seq;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, seq,
+ isolate->factory()->NewRawTwoByteString(character_count_),
+ String);
+
DisallowHeapAllocation no_gc;
uc16* char_buffer = seq->GetChars();
StringBuilderConcatHelper(*subject_,
@@ -3413,22 +3513,14 @@ class ReplacementStringBuilder {
void IncrementCharacterCount(int by) {
if (character_count_ > String::kMaxLength - by) {
- V8::FatalProcessOutOfMemory("String.replace result too large.");
+ STATIC_ASSERT(String::kMaxLength < kMaxInt);
+ character_count_ = kMaxInt;
+ } else {
+ character_count_ += by;
}
- character_count_ += by;
}
private:
- Handle<SeqOneByteString> NewRawOneByteString(int length) {
- return heap_->isolate()->factory()->NewRawOneByteString(length);
- }
-
-
- Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
- return heap_->isolate()->factory()->NewRawTwoByteString(length);
- }
-
-
void AddElement(Object* element) {
ASSERT(element->IsSmi() || element->IsString());
ASSERT(array_builder_.capacity() > array_builder_.length());
@@ -3866,7 +3958,7 @@ void FindStringIndicesDispatch(Isolate* isolate,
template<typename ResultSeqString>
-MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
+MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString(
Isolate* isolate,
Handle<String> subject,
Handle<JSRegExp> pattern_regexp,
@@ -3896,20 +3988,26 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
static_cast<int64_t>(pattern_len)) *
static_cast<int64_t>(matches) +
static_cast<int64_t>(subject_len);
- if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11);
- int result_len = static_cast<int>(result_len_64);
+ int result_len;
+ if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
+ STATIC_ASSERT(String::kMaxLength < kMaxInt);
+ result_len = kMaxInt; // Provoke exception.
+ } else {
+ result_len = static_cast<int>(result_len_64);
+ }
int subject_pos = 0;
int result_pos = 0;
- Handle<ResultSeqString> result;
+ MaybeHandle<SeqString> maybe_res;
if (ResultSeqString::kHasAsciiEncoding) {
- result = Handle<ResultSeqString>::cast(
- isolate->factory()->NewRawOneByteString(result_len));
+ maybe_res = isolate->factory()->NewRawOneByteString(result_len);
} else {
- result = Handle<ResultSeqString>::cast(
- isolate->factory()->NewRawTwoByteString(result_len));
+ maybe_res = isolate->factory()->NewRawTwoByteString(result_len);
}
+ Handle<SeqString> untyped_res;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, untyped_res, maybe_res);
+ Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(untyped_res);
for (int i = 0; i < matches; i++) {
// Copy non-matched subject content.
@@ -3948,7 +4046,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
}
-MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
+MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString(
Isolate* isolate,
Handle<String> subject,
Handle<JSRegExp> regexp,
@@ -3980,11 +4078,11 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
}
RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
int32_t* current_match = global_cache.FetchNext();
if (current_match == NULL) {
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
return *subject;
}
@@ -4026,7 +4124,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
current_match = global_cache.FetchNext();
} while (current_match != NULL);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
if (prev < subject_length) {
builder.EnsureCapacity(2);
@@ -4038,12 +4136,14 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
capture_count,
global_cache.LastSuccessfulMatch());
- return *(builder.ToString());
+ Handle<String> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, builder.ToString());
+ return *result;
}
template <typename ResultSeqString>
-MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
+MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString(
Isolate* isolate,
Handle<String> subject,
Handle<JSRegExp> regexp,
@@ -4063,11 +4163,11 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
}
RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
int32_t* current_match = global_cache.FetchNext();
if (current_match == NULL) {
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
return *subject;
}
@@ -4082,10 +4182,10 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
Handle<ResultSeqString> answer;
if (ResultSeqString::kHasAsciiEncoding) {
answer = Handle<ResultSeqString>::cast(
- isolate->factory()->NewRawOneByteString(new_length));
+ isolate->factory()->NewRawOneByteString(new_length).ToHandleChecked());
} else {
answer = Handle<ResultSeqString>::cast(
- isolate->factory()->NewRawTwoByteString(new_length));
+ isolate->factory()->NewRawTwoByteString(new_length).ToHandleChecked());
}
int prev = 0;
@@ -4104,7 +4204,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
current_match = global_cache.FetchNext();
} while (current_match != NULL);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
RegExpImpl::SetLastMatchInfo(last_match_info,
subject,
@@ -4129,16 +4229,19 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
if (delta == 0) return *answer;
Address end_of_string = answer->address() + string_size;
- isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
- if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
- MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
- }
+ Heap* heap = isolate->heap();
+ // The trimming is performed on a newly allocated object, which is on a
+ // fresly allocated page or on an already swept page. Hence, the sweeper
+ // thread can not get confused with the filler creation. No synchronization
+ // needed.
+ heap->CreateFillerObjectAt(end_of_string, delta);
+ heap->AdjustLiveBytes(answer->address(), -delta, Heap::FROM_MUTATOR);
return *answer;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
+RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
@@ -4147,9 +4250,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
- ASSERT(regexp->GetFlags().is_global());
+ RUNTIME_ASSERT(regexp->GetFlags().is_global());
+ RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
- if (!subject->IsFlat()) subject = FlattenGetString(subject);
+ subject = String::Flatten(subject);
if (replacement->length() == 0) {
if (subject->HasOnlyOneByteChars()) {
@@ -4161,43 +4265,45 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
}
}
- if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
+ replacement = String::Flatten(replacement);
return StringReplaceGlobalRegExpWithString(
isolate, subject, regexp, replacement, last_match_info);
}
-Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
- Handle<String> subject,
- Handle<String> search,
- Handle<String> replace,
- bool* found,
- int recursion_limit) {
- if (recursion_limit == 0) return Handle<String>::null();
+// This may return an empty MaybeHandle if an exception is thrown or
+// we abort due to reaching the recursion limit.
+MaybeHandle<String> StringReplaceOneCharWithString(Isolate* isolate,
+ Handle<String> subject,
+ Handle<String> search,
+ Handle<String> replace,
+ bool* found,
+ int recursion_limit) {
+ StackLimitCheck stackLimitCheck(isolate);
+ if (stackLimitCheck.HasOverflowed() || (recursion_limit == 0)) {
+ return MaybeHandle<String>();
+ }
+ recursion_limit--;
if (subject->IsConsString()) {
ConsString* cons = ConsString::cast(*subject);
Handle<String> first = Handle<String>(cons->first());
Handle<String> second = Handle<String>(cons->second());
- Handle<String> new_first =
- StringReplaceOneCharWithString(isolate,
- first,
- search,
- replace,
- found,
- recursion_limit - 1);
+ Handle<String> new_first;
+ if (!StringReplaceOneCharWithString(
+ isolate, first, search, replace, found, recursion_limit)
+ .ToHandle(&new_first)) {
+ return MaybeHandle<String>();
+ }
if (*found) return isolate->factory()->NewConsString(new_first, second);
- if (new_first.is_null()) return new_first;
-
- Handle<String> new_second =
- StringReplaceOneCharWithString(isolate,
- second,
- search,
- replace,
- found,
- recursion_limit - 1);
+
+ Handle<String> new_second;
+ if (!StringReplaceOneCharWithString(
+ isolate, second, search, replace, found, recursion_limit)
+ .ToHandle(&new_second)) {
+ return MaybeHandle<String>();
+ }
if (*found) return isolate->factory()->NewConsString(first, new_second);
- if (new_second.is_null()) return new_second;
return subject;
} else {
@@ -4205,7 +4311,11 @@ Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
if (index == -1) return subject;
*found = true;
Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
- Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
+ Handle<String> cons1;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, cons1,
+ isolate->factory()->NewConsString(first, replace),
+ String);
Handle<String> second =
isolate->factory()->NewSubString(subject, index + 1, subject->length());
return isolate->factory()->NewConsString(cons1, second);
@@ -4213,7 +4323,7 @@ Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
+RUNTIME_FUNCTION(Runtime_StringReplaceOneCharWithString) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
@@ -4224,19 +4334,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
// retry with a flattened subject string.
const int kRecursionLimit = 0x1000;
bool found = false;
- Handle<String> result = StringReplaceOneCharWithString(isolate,
- subject,
- search,
- replace,
- &found,
- kRecursionLimit);
- if (!result.is_null()) return *result;
- return *StringReplaceOneCharWithString(isolate,
- FlattenGetString(subject),
- search,
- replace,
- &found,
- kRecursionLimit);
+ Handle<String> result;
+ if (StringReplaceOneCharWithString(
+ isolate, subject, search, replace, &found, kRecursionLimit)
+ .ToHandle(&result)) {
+ return *result;
+ }
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
+
+ subject = String::Flatten(subject);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ StringReplaceOneCharWithString(
+ isolate, subject, search, replace, &found, kRecursionLimit));
+ return *result;
}
@@ -4256,8 +4367,8 @@ int Runtime::StringMatch(Isolate* isolate,
int subject_length = sub->length();
if (start_index + pattern_length > subject_length) return -1;
- if (!sub->IsFlat()) FlattenString(sub);
- if (!pat->IsFlat()) FlattenString(pat);
+ sub = String::Flatten(sub);
+ pat = String::Flatten(pat);
DisallowHeapAllocation no_gc; // ensure vectors stay valid
// Extract flattened substrings of cons strings before determining asciiness.
@@ -4292,20 +4403,19 @@ int Runtime::StringMatch(Isolate* isolate,
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
+RUNTIME_FUNCTION(Runtime_StringIndexOf) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, index, 2);
- Object* index = args[2];
uint32_t start_index;
if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
- int position =
- Runtime::StringMatch(isolate, sub, pat, start_index);
+ int position = Runtime::StringMatch(isolate, sub, pat, start_index);
return Smi::FromInt(position);
}
@@ -4345,14 +4455,14 @@ static int StringMatchBackwards(Vector<const schar> subject,
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
+RUNTIME_FUNCTION(Runtime_StringLastIndexOf) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, index, 2);
- Object* index = args[2];
uint32_t start_index;
if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
@@ -4367,8 +4477,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
return Smi::FromInt(start_index);
}
- if (!sub->IsFlat()) FlattenString(sub);
- if (!pat->IsFlat()) FlattenString(pat);
+ sub = String::Flatten(sub);
+ pat = String::Flatten(pat);
int position = -1;
DisallowHeapAllocation no_gc; // ensure vectors stay valid
@@ -4404,14 +4514,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_StringLocaleCompare) {
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(String, str1, 0);
- CONVERT_ARG_CHECKED(String, str2, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
- if (str1 == str2) return Smi::FromInt(0); // Equal.
+ if (str1.is_identical_to(str2)) return Smi::FromInt(0); // Equal.
int str1_length = str1->length();
int str2_length = str2->length();
@@ -4431,32 +4541,28 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
int d = str1->Get(0) - str2->Get(0);
if (d != 0) return Smi::FromInt(d);
- str1->TryFlatten();
- str2->TryFlatten();
+ str1 = String::Flatten(str1);
+ str2 = String::Flatten(str2);
- ConsStringIteratorOp* op1 =
- isolate->runtime_state()->string_locale_compare_it1();
- ConsStringIteratorOp* op2 =
- isolate->runtime_state()->string_locale_compare_it2();
- // TODO(dcarney) Can do array compares here more efficiently.
- StringCharacterStream stream1(str1, op1);
- StringCharacterStream stream2(str2, op2);
+ DisallowHeapAllocation no_gc;
+ String::FlatContent flat1 = str1->GetFlatContent();
+ String::FlatContent flat2 = str2->GetFlatContent();
for (int i = 0; i < end; i++) {
- uint16_t char1 = stream1.GetNext();
- uint16_t char2 = stream2.GetNext();
- if (char1 != char2) return Smi::FromInt(char1 - char2);
+ if (flat1.Get(i) != flat2.Get(i)) {
+ return Smi::FromInt(flat1.Get(i) - flat2.Get(i));
+ }
}
return Smi::FromInt(str1_length - str2_length);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_SubString) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
- CONVERT_ARG_CHECKED(String, value, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
int start, end;
// We have a fast integer-only case here to avoid a conversion to double in
// the common case where from and to are Smis.
@@ -4473,22 +4579,25 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
}
RUNTIME_ASSERT(end >= start);
RUNTIME_ASSERT(start >= 0);
- RUNTIME_ASSERT(end <= value->length());
+ RUNTIME_ASSERT(end <= string->length());
isolate->counters()->sub_string_runtime()->Increment();
- return value->SubString(start, end);
+
+ return *isolate->factory()->NewSubString(string, start, end);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
+RUNTIME_FUNCTION(Runtime_StringMatch) {
HandleScope handles(isolate);
- ASSERT_EQ(3, args.length());
+ ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
+ RUNTIME_ASSERT(regexp_info->HasFastObjectElements());
+
RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
int capture_count = regexp->CaptureCount();
@@ -4502,7 +4611,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
offsets.Add(match[1], zone_scope.zone()); // end
}
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
if (offsets.length() == 0) {
// Not a single match.
@@ -4536,7 +4645,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
// Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
// separate last match info. See comment on that function.
template<bool has_capture>
-static MaybeObject* SearchRegExpMultiple(
+static Object* SearchRegExpMultiple(
Isolate* isolate,
Handle<String> subject,
Handle<JSRegExp> regexp,
@@ -4560,7 +4669,7 @@ static MaybeObject* SearchRegExpMultiple(
Handle<FixedArray> cached_fixed_array =
Handle<FixedArray>(FixedArray::cast(*cached_answer));
// The cache FixedArray is a COW-array and can therefore be reused.
- isolate->factory()->SetContent(result_array, cached_fixed_array);
+ JSArray::SetContent(result_array, cached_fixed_array);
// The actual length of the result array is stored in the last element of
// the backing store (the backing FixedArray may have a larger capacity).
Object* cached_fixed_array_last_element =
@@ -4574,14 +4683,13 @@ static MaybeObject* SearchRegExpMultiple(
}
RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
- Handle<FixedArray> result_elements;
- if (result_array->HasFastObjectElements()) {
- result_elements =
- Handle<FixedArray>(FixedArray::cast(result_array->elements()));
- }
- if (result_elements.is_null() || result_elements->length() < 16) {
+ // Ensured in Runtime_RegExpExecMultiple.
+ ASSERT(result_array->HasFastObjectElements());
+ Handle<FixedArray> result_elements(
+ FixedArray::cast(result_array->elements()));
+ if (result_elements->length() < 16) {
result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
}
@@ -4650,7 +4758,7 @@ static MaybeObject* SearchRegExpMultiple(
}
}
- if (global_cache.HasException()) return Failure::Exception();
+ if (global_cache.HasException()) return isolate->heap()->exception();
if (match_start >= 0) {
// Finished matching, with at least one match.
@@ -4671,10 +4779,10 @@ static MaybeObject* SearchRegExpMultiple(
fixed_array->set(fixed_array->length() - 1,
Smi::FromInt(builder.length()));
// Cache the result and turn the FixedArray into a COW array.
- RegExpResultsCache::Enter(isolate->heap(),
- *subject,
- regexp->data(),
- *fixed_array,
+ RegExpResultsCache::Enter(isolate,
+ subject,
+ handle(regexp->data(), isolate),
+ fixed_array,
RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
}
return *builder.ToJSArray(result_array);
@@ -4687,17 +4795,19 @@ static MaybeObject* SearchRegExpMultiple(
// This is only called for StringReplaceGlobalRegExpWithFunction. This sets
// lastMatchInfoOverride to maintain the last match info, so we don't need to
// set any other last match array info.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
+RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) {
HandleScope handles(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
- if (!subject->IsFlat()) FlattenString(subject);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
+ RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
+ RUNTIME_ASSERT(result_array->HasFastObjectElements());
- ASSERT(regexp->GetFlags().is_global());
+ subject = String::Flatten(subject);
+ RUNTIME_ASSERT(regexp->GetFlags().is_global());
if (regexp->CaptureCount() == 0) {
return SearchRegExpMultiple<false>(
@@ -4709,8 +4819,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToRadixString) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(radix, 1);
RUNTIME_ASSERT(2 <= radix && radix <= 36);
@@ -4721,7 +4831,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
if (value >= 0 && value < radix) {
// Character array used for conversion.
static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
- return isolate->heap()->
+ return *isolate->factory()->
LookupSingleCharacterStringFromCode(kCharTable[value]);
}
}
@@ -4729,80 +4839,76 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
// Slow case.
CONVERT_DOUBLE_ARG_CHECKED(value, 0);
if (std::isnan(value)) {
- return *isolate->factory()->nan_string();
+ return isolate->heap()->nan_string();
}
if (std::isinf(value)) {
if (value < 0) {
- return *isolate->factory()->minus_infinity_string();
+ return isolate->heap()->minus_infinity_string();
}
- return *isolate->factory()->infinity_string();
+ return isolate->heap()->infinity_string();
}
char* str = DoubleToRadixCString(value, radix);
- MaybeObject* result =
- isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
+ Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
DeleteArray(str);
- return result;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToFixed) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(value, 0);
CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
int f = FastD2IChecked(f_number);
- RUNTIME_ASSERT(f >= 0);
+ // See DoubleToFixedCString for these constants:
+ RUNTIME_ASSERT(f >= 0 && f <= 20);
+ RUNTIME_ASSERT(!Double(value).IsSpecial());
char* str = DoubleToFixedCString(value, f);
- MaybeObject* res =
- isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
+ Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
DeleteArray(str);
- return res;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToExponential) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(value, 0);
CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
int f = FastD2IChecked(f_number);
RUNTIME_ASSERT(f >= -1 && f <= 20);
+ RUNTIME_ASSERT(!Double(value).IsSpecial());
char* str = DoubleToExponentialCString(value, f);
- MaybeObject* res =
- isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
+ Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
DeleteArray(str);
- return res;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToPrecision) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(value, 0);
CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
int f = FastD2IChecked(f_number);
RUNTIME_ASSERT(f >= 1 && f <= 21);
+ RUNTIME_ASSERT(!Double(value).IsSpecial());
char* str = DoubleToPrecisionCString(value, f);
- MaybeObject* res =
- isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
+ Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
DeleteArray(str);
- return res;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsValidSmi) {
- HandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_IsValidSmi) {
+ SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
- if (Smi::IsValid(number)) {
- return isolate->heap()->true_value();
- } else {
- return isolate->heap()->false_value();
- }
+ return isolate->heap()->ToBoolean(Smi::IsValid(number));
}
@@ -4810,30 +4916,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsValidSmi) {
// string->Get(index).
static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
if (index < static_cast<uint32_t>(string->length())) {
- string->TryFlatten();
- return LookupSingleCharacterStringFromCode(
- string->GetIsolate(),
- string->Get(index));
+ Factory* factory = string->GetIsolate()->factory();
+ return factory->LookupSingleCharacterStringFromCode(
+ String::Flatten(string)->Get(index));
}
return Execution::CharAt(string, index);
}
-MaybeObject* Runtime::GetElementOrCharAtOrFail(Isolate* isolate,
- Handle<Object> object,
- uint32_t index) {
- CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
- GetElementOrCharAt(isolate, object, index));
-}
-
-
-MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
- Handle<Object> object,
- uint32_t index) {
+MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
+ Handle<Object> object,
+ uint32_t index) {
// Handle [] indexing on Strings
if (object->IsString()) {
Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
- if (!result->IsUndefined()) return *result;
+ if (!result->IsUndefined()) return result;
}
// Handle [] indexing on String objects
@@ -4841,67 +4938,57 @@ MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
Handle<JSValue> js_value = Handle<JSValue>::cast(object);
Handle<Object> result =
GetCharAt(Handle<String>(String::cast(js_value->value())), index);
- if (!result->IsUndefined()) return *result;
+ if (!result->IsUndefined()) return result;
}
+ Handle<Object> result;
if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
- return object->GetPrototype(isolate)->GetElement(isolate, index);
+ Handle<Object> proto(object->GetPrototype(isolate), isolate);
+ return Object::GetElement(isolate, proto, index);
+ } else {
+ return Object::GetElement(isolate, object, index);
}
-
- return object->GetElement(isolate, index);
}
-static Handle<Name> ToName(Isolate* isolate, Handle<Object> key) {
+MUST_USE_RESULT
+static MaybeHandle<Name> ToName(Isolate* isolate, Handle<Object> key) {
if (key->IsName()) {
return Handle<Name>::cast(key);
} else {
- bool has_pending_exception = false;
- Handle<Object> converted =
- Execution::ToString(isolate, key, &has_pending_exception);
- if (has_pending_exception) return Handle<Name>();
+ Handle<Object> converted;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, key), Name);
return Handle<Name>::cast(converted);
}
}
-MaybeObject* Runtime::HasObjectProperty(Isolate* isolate,
- Handle<JSReceiver> object,
- Handle<Object> key) {
- HandleScope scope(isolate);
-
+MaybeHandle<Object> Runtime::HasObjectProperty(Isolate* isolate,
+ Handle<JSReceiver> object,
+ Handle<Object> key) {
// Check if the given key is an array index.
uint32_t index;
if (key->ToArrayIndex(&index)) {
- return isolate->heap()->ToBoolean(JSReceiver::HasElement(object, index));
+ return isolate->factory()->ToBoolean(JSReceiver::HasElement(object, index));
}
// Convert the key to a name - possibly by calling back into JavaScript.
- Handle<Name> name = ToName(isolate, key);
- RETURN_IF_EMPTY_HANDLE(isolate, name);
-
- return isolate->heap()->ToBoolean(JSReceiver::HasProperty(object, name));
-}
+ Handle<Name> name;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
-MaybeObject* Runtime::GetObjectPropertyOrFail(
- Isolate* isolate,
- Handle<Object> object,
- Handle<Object> key) {
- CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
- GetObjectProperty(isolate, object, key));
+ return isolate->factory()->ToBoolean(JSReceiver::HasProperty(object, name));
}
-MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
- Handle<Object> object,
- Handle<Object> key) {
- HandleScope scope(isolate);
+MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
+ Handle<Object> object,
+ Handle<Object> key) {
if (object->IsUndefined() || object->IsNull()) {
Handle<Object> args[2] = { key, object };
- Handle<Object> error =
+ return isolate->Throw<Object>(
isolate->factory()->NewTypeError("non_object_property_load",
- HandleVector(args, 2));
- return isolate->Throw(*error);
+ HandleVector(args, 2)));
}
// Check if the given key is an array index.
@@ -4911,60 +4998,68 @@ MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
}
// Convert the key to a name - possibly by calling back into JavaScript.
- Handle<Name> name = ToName(isolate, key);
- RETURN_IF_EMPTY_HANDLE(isolate, name);
+ Handle<Name> name;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
// Check if the name is trivially convertible to an index and get
// the element if so.
if (name->AsArrayIndex(&index)) {
return GetElementOrCharAt(isolate, object, index);
} else {
- return object->GetProperty(*name);
+ return Object::GetProperty(object, name);
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_GetProperty) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- Handle<Object> object = args.at<Object>(0);
- Handle<Object> key = args.at<Object>(1);
-
- return Runtime::GetObjectProperty(isolate, object, key);
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Runtime::GetObjectProperty(isolate, object, key));
+ return *result;
}
// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
+
// Fast cases for getting named properties of the receiver JSObject
// itself.
//
- // The global proxy objects has to be excluded since LocalLookup on
+ // The global proxy objects has to be excluded since LookupOwn on
// the global proxy object can return a valid result even though the
// global proxy object never has properties. This is the case
// because the global proxy object forwards everything to its hidden
- // prototype including local lookups.
+ // prototype including own lookups.
//
// Additionally, we need to make sure that we do not cache results
// for objects that require access checks.
- if (args[0]->IsJSObject()) {
- if (!args[0]->IsJSGlobalProxy() &&
- !args[0]->IsAccessCheckNeeded() &&
- args[1]->IsName()) {
- JSObject* receiver = JSObject::cast(args[0]);
- Name* key = Name::cast(args[1]);
+ if (receiver_obj->IsJSObject()) {
+ if (!receiver_obj->IsJSGlobalProxy() &&
+ !receiver_obj->IsAccessCheckNeeded() &&
+ key_obj->IsName()) {
+ DisallowHeapAllocation no_allocation;
+ Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
+ Handle<Name> key = Handle<Name>::cast(key_obj);
if (receiver->HasFastProperties()) {
// Attempt to use lookup cache.
- Map* receiver_map = receiver->map();
+ Handle<Map> receiver_map(receiver->map(), isolate);
KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
- int offset = keyed_lookup_cache->Lookup(receiver_map, key);
- if (offset != -1) {
+ int index = keyed_lookup_cache->Lookup(receiver_map, key);
+ if (index != -1) {
// Doubles are not cached, so raw read the value.
- Object* value = receiver->RawFastPropertyAt(offset);
+ Object* value = receiver->RawFastPropertyAt(
+ FieldIndex::ForKeyedLookupCacheIndex(*receiver_map, index));
return value->IsTheHole()
? isolate->heap()->undefined_value()
: value;
@@ -4972,16 +5067,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
// Lookup cache miss. Perform lookup and update the cache if
// appropriate.
LookupResult result(isolate);
- receiver->LocalLookup(key, &result);
+ receiver->LookupOwn(key, &result);
if (result.IsField()) {
- int offset = result.GetFieldIndex().field_index();
+ FieldIndex field_index = result.GetFieldIndex();
// Do not track double fields in the keyed lookup cache. Reading
// double values requires boxing.
- if (!FLAG_track_double_fields ||
- !result.representation().IsDouble()) {
- keyed_lookup_cache->Update(receiver_map, key, offset);
+ if (!result.representation().IsDouble()) {
+ keyed_lookup_cache->Update(receiver_map, key,
+ field_index.GetKeyedLookupCacheIndex());
}
- return receiver->FastPropertyAt(result.representation(), offset);
+ AllowHeapAllocation allow_allocation;
+ return *JSObject::FastPropertyAt(receiver, result.representation(),
+ field_index);
}
} else {
// Attempt dictionary lookup.
@@ -4996,48 +5093,46 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
// If value is the hole do the general lookup.
}
}
- } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
+ } else if (FLAG_smi_only_arrays && key_obj->IsSmi()) {
// JSObject without a name key. If the key is a Smi, check for a
// definite out-of-bounds access to elements, which is a strong indicator
// that subsequent accesses will also call the runtime. Proactively
// transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
// doubles for those future calls in the case that the elements would
// become FAST_DOUBLE_ELEMENTS.
- Handle<JSObject> js_object(args.at<JSObject>(0));
+ Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
ElementsKind elements_kind = js_object->GetElementsKind();
if (IsFastDoubleElementsKind(elements_kind)) {
- FixedArrayBase* elements = js_object->elements();
- if (args.at<Smi>(1)->value() >= elements->length()) {
+ Handle<Smi> key = Handle<Smi>::cast(key_obj);
+ if (key->value() >= js_object->elements()->length()) {
if (IsFastHoleyElementsKind(elements_kind)) {
elements_kind = FAST_HOLEY_ELEMENTS;
} else {
elements_kind = FAST_ELEMENTS;
}
- MaybeObject* maybe_object = TransitionElements(js_object,
- elements_kind,
- isolate);
- if (maybe_object->IsFailure()) return maybe_object;
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate, TransitionElements(js_object, elements_kind, isolate));
}
} else {
ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
!IsFastElementsKind(elements_kind));
}
}
- } else if (args[0]->IsString() && args[1]->IsSmi()) {
+ } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
// Fast case for string indexing using [] with a smi index.
- HandleScope scope(isolate);
- Handle<String> str = args.at<String>(0);
+ Handle<String> str = Handle<String>::cast(receiver_obj);
int index = args.smi_at(1);
if (index >= 0 && index < str->length()) {
- Handle<Object> result = GetCharAt(str, index);
- return *result;
+ return *GetCharAt(str, index);
}
}
// Fall back to GetObjectProperty.
- return Runtime::GetObjectProperty(isolate,
- args.at<Object>(0),
- args.at<Object>(1));
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Runtime::GetObjectProperty(isolate, receiver_obj, key_obj));
+ return *result;
}
@@ -5052,7 +5147,7 @@ static bool IsValidAccessor(Handle<Object> obj) {
// Steps 9c & 12 - replace an existing data property with an accessor property.
// Step 12 - update an existing accessor property with an accessor or generic
// descriptor.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
+RUNTIME_FUNCTION(Runtime_DefineOrRedefineAccessorProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
@@ -5067,8 +5162,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
bool fast = obj->HasFastProperties();
+ // DefineAccessor checks access rights.
JSObject::DefineAccessor(obj, name, getter, setter, attr);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
if (fast) JSObject::TransformToFastProperties(obj, 0);
return isolate->heap()->undefined_value();
}
@@ -5080,7 +5176,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
// Steps 9b & 12 - replace an existing accessor property with a data property.
// Step 12 - update an existing data property with a data or generic
// descriptor.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
+RUNTIME_FUNCTION(Runtime_DefineOrRedefineDataProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
@@ -5090,35 +5186,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
- LookupResult lookup(isolate);
- js_object->LocalLookupRealNamedProperty(*name, &lookup);
-
- // Special case for callback properties.
- if (lookup.IsPropertyCallbacks()) {
- Handle<Object> callback(lookup.GetCallbackObject(), isolate);
- // To be compatible with Safari we do not change the value on API objects
- // in Object.defineProperty(). Firefox disagrees here, and actually changes
- // the value.
- if (callback->IsAccessorInfo()) {
- return isolate->heap()->undefined_value();
- }
- // Avoid redefining foreign callback as data property, just use the stored
- // setter to update the value instead.
- // TODO(mstarzinger): So far this only works if property attributes don't
- // change, this should be fixed once we cleanup the underlying code.
- if (callback->IsForeign() && lookup.GetAttributes() == attr) {
- Handle<Object> result_object =
- JSObject::SetPropertyWithCallback(js_object,
- callback,
- name,
- obj_value,
- handle(lookup.holder()),
- kStrictMode);
- RETURN_IF_EMPTY_HANDLE(isolate, result_object);
- return *result_object;
- }
+ // Check access rights if needed.
+ if (js_object->IsAccessCheckNeeded() &&
+ !isolate->MayNamedAccess(js_object, name, v8::ACCESS_SET)) {
+ return isolate->heap()->undefined_value();
}
+ LookupResult lookup(isolate);
+ js_object->LookupOwnRealNamedProperty(name, &lookup);
+
// Take special care when attributes are different and there is already
// a property. For simplicity we normalize the property which enables us
// to not worry about changing the instance_descriptor and creating a new
@@ -5133,60 +5209,54 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
// we don't have to check for null.
js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
}
- JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
+
+ if (attr != lookup.GetAttributes() ||
+ (lookup.IsPropertyCallbacks() &&
+ !lookup.GetCallbackObject()->IsAccessorInfo())) {
+ JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
+ }
+
// Use IgnoreAttributes version since a readonly property may be
// overridden and SetProperty does not allow this.
- Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
- js_object, name, obj_value, attr);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSObject::SetOwnPropertyIgnoreAttributes(
+ js_object, name, obj_value, attr,
+ Object::OPTIMAL_REPRESENTATION,
+ ALLOW_AS_CONSTANT,
+ JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
+ JSReceiver::MAY_BE_STORE_FROM_KEYED,
+ JSObject::DONT_FORCE_FIELD));
return *result;
}
- Handle<Object> result = Runtime::ForceSetObjectProperty(isolate, js_object,
- name,
- obj_value,
- attr);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Runtime::ForceSetObjectProperty(
+ js_object, name, obj_value, attr,
+ JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED));
return *result;
}
// Return property without being observable by accessors or interceptors.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_GetDataProperty) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
- LookupResult lookup(isolate);
- object->LookupRealNamedProperty(*key, &lookup);
- if (!lookup.IsFound()) return isolate->heap()->undefined_value();
- switch (lookup.type()) {
- case NORMAL:
- return lookup.holder()->GetNormalizedProperty(&lookup);
- case FIELD:
- return lookup.holder()->FastPropertyAt(
- lookup.representation(),
- lookup.GetFieldIndex().field_index());
- case CONSTANT:
- return lookup.GetConstant();
- case CALLBACKS:
- case HANDLER:
- case INTERCEPTOR:
- case TRANSITION:
- return isolate->heap()->undefined_value();
- case NONEXISTENT:
- UNREACHABLE();
- }
- return isolate->heap()->undefined_value();
+ return *JSObject::GetDataProperty(object, key);
}
-Handle<Object> Runtime::SetObjectProperty(Isolate* isolate,
- Handle<Object> object,
- Handle<Object> key,
- Handle<Object> value,
- PropertyAttributes attr,
- StrictModeFlag strict_mode) {
+MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
+ Handle<Object> object,
+ Handle<Object> key,
+ Handle<Object> value,
+ PropertyAttributes attr,
+ StrictMode strict_mode) {
SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
if (object->IsUndefined() || object->IsNull()) {
@@ -5194,15 +5264,17 @@ Handle<Object> Runtime::SetObjectProperty(Isolate* isolate,
Handle<Object> error =
isolate->factory()->NewTypeError("non_object_property_store",
HandleVector(args, 2));
- isolate->Throw(*error);
- return Handle<Object>();
+ return isolate->Throw<Object>(error);
}
if (object->IsJSProxy()) {
- bool has_pending_exception = false;
- Handle<Object> name_object = key->IsSymbol()
- ? key : Execution::ToString(isolate, key, &has_pending_exception);
- if (has_pending_exception) return Handle<Object>(); // exception
+ Handle<Object> name_object;
+ if (key->IsSymbol()) {
+ name_object = key;
+ } else {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, name_object, Execution::ToString(isolate, key), Object);
+ }
Handle<Name> name = Handle<Name>::cast(name_object);
return JSReceiver::SetProperty(Handle<JSProxy>::cast(object), name, value,
attr,
@@ -5228,21 +5300,19 @@ Handle<Object> Runtime::SetObjectProperty(Isolate* isolate,
return value;
}
- js_object->ValidateElements();
- if (js_object->HasExternalArrayElements()) {
+ JSObject::ValidateElements(js_object);
+ if (js_object->HasExternalArrayElements() ||
+ js_object->HasFixedTypedArrayElements()) {
if (!value->IsNumber() && !value->IsUndefined()) {
- bool has_exception;
- Handle<Object> number =
- Execution::ToNumber(isolate, value, &has_exception);
- if (has_exception) return Handle<Object>(); // exception
- value = number;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value, Execution::ToNumber(isolate, value), Object);
}
}
- Handle<Object> result = JSObject::SetElement(js_object, index, value, attr,
- strict_mode,
- true,
- set_mode);
- js_object->ValidateElements();
+
+ MaybeHandle<Object> result = JSObject::SetElement(
+ js_object, index, value, attr, strict_mode, true, set_mode);
+ JSObject::ValidateElements(js_object);
+
return result.is_null() ? result : value;
}
@@ -5251,44 +5321,40 @@ Handle<Object> Runtime::SetObjectProperty(Isolate* isolate,
if (name->AsArrayIndex(&index)) {
if (js_object->HasExternalArrayElements()) {
if (!value->IsNumber() && !value->IsUndefined()) {
- bool has_exception;
- Handle<Object> number =
- Execution::ToNumber(isolate, value, &has_exception);
- if (has_exception) return Handle<Object>(); // exception
- value = number;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value, Execution::ToNumber(isolate, value), Object);
}
}
- return JSObject::SetElement(js_object, index, value, attr, strict_mode,
- true,
- set_mode);
+ return JSObject::SetElement(js_object, index, value, attr,
+ strict_mode, true, set_mode);
} else {
- if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
+ if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
}
}
// Call-back into JavaScript to convert the key to a string.
- bool has_pending_exception = false;
- Handle<Object> converted =
- Execution::ToString(isolate, key, &has_pending_exception);
- if (has_pending_exception) return Handle<Object>(); // exception
+ Handle<Object> converted;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, key), Object);
Handle<String> name = Handle<String>::cast(converted);
if (name->AsArrayIndex(&index)) {
- return JSObject::SetElement(js_object, index, value, attr, strict_mode,
- true,
- set_mode);
+ return JSObject::SetElement(js_object, index, value, attr,
+ strict_mode, true, set_mode);
} else {
return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
}
}
-Handle<Object> Runtime::ForceSetObjectProperty(Isolate* isolate,
- Handle<JSObject> js_object,
- Handle<Object> key,
- Handle<Object> value,
- PropertyAttributes attr) {
+MaybeHandle<Object> Runtime::ForceSetObjectProperty(
+ Handle<JSObject> js_object,
+ Handle<Object> key,
+ Handle<Object> value,
+ PropertyAttributes attr,
+ JSReceiver::StoreFromKeyed store_from_keyed) {
+ Isolate* isolate = js_object->GetIsolate();
// Check if the given key is an array index.
uint32_t index;
if (key->ToArrayIndex(&index)) {
@@ -5303,48 +5369,46 @@ Handle<Object> Runtime::ForceSetObjectProperty(Isolate* isolate,
return value;
}
- return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
- false,
- DEFINE_PROPERTY);
+ return JSObject::SetElement(js_object, index, value, attr,
+ SLOPPY, false, DEFINE_PROPERTY);
}
if (key->IsName()) {
Handle<Name> name = Handle<Name>::cast(key);
if (name->AsArrayIndex(&index)) {
- return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
- false,
- DEFINE_PROPERTY);
+ return JSObject::SetElement(js_object, index, value, attr,
+ SLOPPY, false, DEFINE_PROPERTY);
} else {
- if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
- return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name,
- value, attr);
+ if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
+ return JSObject::SetOwnPropertyIgnoreAttributes(
+ js_object, name, value, attr, Object::OPTIMAL_REPRESENTATION,
+ ALLOW_AS_CONSTANT, JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
+ store_from_keyed);
}
}
// Call-back into JavaScript to convert the key to a string.
- bool has_pending_exception = false;
- Handle<Object> converted =
- Execution::ToString(isolate, key, &has_pending_exception);
- if (has_pending_exception) return Handle<Object>(); // exception
+ Handle<Object> converted;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, key), Object);
Handle<String> name = Handle<String>::cast(converted);
if (name->AsArrayIndex(&index)) {
- return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
- false,
- DEFINE_PROPERTY);
+ return JSObject::SetElement(js_object, index, value, attr,
+ SLOPPY, false, DEFINE_PROPERTY);
} else {
- return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name, value,
- attr);
+ return JSObject::SetOwnPropertyIgnoreAttributes(
+ js_object, name, value, attr, Object::OPTIMAL_REPRESENTATION,
+ ALLOW_AS_CONSTANT, JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
+ store_from_keyed);
}
}
-MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
- Handle<JSReceiver> receiver,
- Handle<Object> key,
- JSReceiver::DeleteMode mode) {
- HandleScope scope(isolate);
-
+MaybeHandle<Object> Runtime::DeleteObjectProperty(Isolate* isolate,
+ Handle<JSReceiver> receiver,
+ Handle<Object> key,
+ JSReceiver::DeleteMode mode) {
// Check if the given key is an array index.
uint32_t index;
if (key->ToArrayIndex(&index)) {
@@ -5355,12 +5419,10 @@ MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
// underlying string does nothing with the deletion, we can ignore
// such deletions.
if (receiver->IsStringObjectWithCharacterAt(index)) {
- return isolate->heap()->true_value();
+ return isolate->factory()->true_value();
}
- Handle<Object> result = JSReceiver::DeleteElement(receiver, index, mode);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
- return *result;
+ return JSReceiver::DeleteElement(receiver, index, mode);
}
Handle<Name> name;
@@ -5368,21 +5430,30 @@ MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
name = Handle<Name>::cast(key);
} else {
// Call-back into JavaScript to convert the key to a string.
- bool has_pending_exception = false;
- Handle<Object> converted = Execution::ToString(
- isolate, key, &has_pending_exception);
- if (has_pending_exception) return Failure::Exception();
+ Handle<Object> converted;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, key), Object);
name = Handle<String>::cast(converted);
}
- if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
- Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
- return *result;
+ if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
+ return JSReceiver::DeleteProperty(receiver, name, mode);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
+RUNTIME_FUNCTION(Runtime_SetHiddenProperty) {
+ HandleScope scope(isolate);
+ RUNTIME_ASSERT(args.length() == 3);
+
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, key, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
+ RUNTIME_ASSERT(key->IsUniqueName());
+ return *JSObject::SetHiddenProperty(object, key, value);
+}
+
+
+RUNTIME_FUNCTION(Runtime_SetProperty) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
@@ -5396,22 +5467,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
PropertyAttributes attributes =
static_cast<PropertyAttributes>(unchecked_attributes);
- StrictModeFlag strict_mode = kNonStrictMode;
+ StrictMode strict_mode = SLOPPY;
if (args.length() == 5) {
- CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
- strict_mode = strict_mode_flag;
+ CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_arg, 4);
+ strict_mode = strict_mode_arg;
}
- Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
- value,
- attributes,
- strict_mode);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Runtime::SetObjectProperty(
+ isolate, object, key, value, attributes, strict_mode));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
+RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
@@ -5424,7 +5495,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
// Set the native flag on the function.
// This is used to decide if we should transform null and undefined
// into the global object when doing call and apply.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
+RUNTIME_FUNCTION(Runtime_SetNativeFlag) {
SealHandleScope shs(isolate);
RUNTIME_ASSERT(args.length() == 1);
@@ -5438,11 +5509,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInlineBuiltinFlag) {
+RUNTIME_FUNCTION(Runtime_SetInlineBuiltinFlag) {
SealHandleScope shs(isolate);
RUNTIME_ASSERT(args.length() == 1);
-
- Handle<Object> object = args.at<Object>(0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(*object);
@@ -5452,12 +5522,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInlineBuiltinFlag) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
+RUNTIME_FUNCTION(Runtime_StoreArrayLiteralElement) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_SMI_ARG_CHECKED(store_index, 1);
- Handle<Object> value = args.at<Object>(2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
CONVERT_SMI_ARG_CHECKED(literal_index, 4);
@@ -5491,16 +5561,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
HeapNumber* number = HeapNumber::cast(*value);
double_array->set(store_index, number->Number());
} else {
- ASSERT(IsFastSmiElementsKind(elements_kind) ||
- IsFastDoubleElementsKind(elements_kind));
- ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
- ? FAST_HOLEY_ELEMENTS
- : FAST_ELEMENTS;
- JSObject::TransitionElementsKind(object, transitioned_kind);
- if (IsMoreGeneralElementsKindTransition(
- boilerplate_object->GetElementsKind(),
- transitioned_kind)) {
- JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
+ if (!IsFastObjectElementsKind(elements_kind)) {
+ ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
+ ? FAST_HOLEY_ELEMENTS
+ : FAST_ELEMENTS;
+ JSObject::TransitionElementsKind(object, transitioned_kind);
+ ElementsKind boilerplate_elements_kind =
+ boilerplate_object->GetElementsKind();
+ if (IsMoreGeneralElementsKindTransition(boilerplate_elements_kind,
+ transitioned_kind)) {
+ JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
+ }
}
FixedArray* object_array = FixedArray::cast(object->elements());
object_array->set(store_index, *value);
@@ -5511,29 +5582,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
// Check whether debugger and is about to step into the callback that is passed
// to a built-in function such as Array.forEach.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
- SealHandleScope shs(isolate);
-#ifdef ENABLE_DEBUGGER_SUPPORT
- if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
+RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) {
+ ASSERT(args.length() == 1);
+ if (!isolate->debug()->is_active() || !isolate->debug()->StepInActive()) {
return isolate->heap()->false_value();
}
CONVERT_ARG_CHECKED(Object, callback, 0);
// We do not step into the callback if it's a builtin or not even a function.
- if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
- return isolate->heap()->false_value();
- }
- return isolate->heap()->true_value();
-#else
- return isolate->heap()->false_value();
-#endif // ENABLE_DEBUGGER_SUPPORT
+ return isolate->heap()->ToBoolean(
+ callback->IsJSFunction() && !JSFunction::cast(callback)->IsBuiltin());
}
// Set one shot breakpoints for the callback function that is passed to a
// built-in function such as Array.forEach to enable stepping into the callback.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
- SealHandleScope shs(isolate);
-#ifdef ENABLE_DEBUGGER_SUPPORT
+RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
+ ASSERT(args.length() == 1);
Debug* debug = isolate->debug();
if (!debug->IsStepping()) return isolate->heap()->undefined_value();
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
@@ -5543,14 +5607,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
// again, we need to clear the step out at this point.
debug->ClearStepOut();
debug->FloodWithOneShot(callback);
-#endif // ENABLE_DEBUGGER_SUPPORT
return isolate->heap()->undefined_value();
}
-// Set a local property, even if it is READ_ONLY. If the property does not
+// The argument is a closure that is kept until the epilogue is called.
+// On exception, the closure is called, which returns the promise if the
+// exception is considered uncaught, or undefined otherwise.
+RUNTIME_FUNCTION(Runtime_DebugPromiseHandlePrologue) {
+ ASSERT(args.length() == 1);
+ HandleScope scope(isolate);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, promise_getter, 0);
+ isolate->debug()->PromiseHandlePrologue(promise_getter);
+ return isolate->heap()->undefined_value();
+}
+
+
+RUNTIME_FUNCTION(Runtime_DebugPromiseHandleEpilogue) {
+ ASSERT(args.length() == 0);
+ SealHandleScope shs(isolate);
+ isolate->debug()->PromiseHandleEpilogue();
+ return isolate->heap()->undefined_value();
+}
+
+
+// Set an own property, even if it is READ_ONLY. If the property does not
// exist, it will be added with attributes NONE.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
+RUNTIME_FUNCTION(Runtime_IgnoreAttributesAndSetProperty) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -5565,31 +5648,35 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
(unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
attributes = static_cast<PropertyAttributes>(unchecked_value);
}
- Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
- object, name, value, attributes);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSObject::SetOwnPropertyIgnoreAttributes(
+ object, name, value, attributes));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
+RUNTIME_FUNCTION(Runtime_DeleteProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
- JSReceiver::DeleteMode delete_mode = (strict_mode == kStrictMode)
+ JSReceiver::DeleteMode delete_mode = strict_mode == STRICT
? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
- Handle<Object> result = JSReceiver::DeleteProperty(object, key, delete_mode);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSReceiver::DeleteProperty(object, key, delete_mode));
return *result;
}
-static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
- Handle<JSObject> object,
- Handle<Name> key) {
- if (JSReceiver::HasLocalProperty(object, key)) {
+static Object* HasOwnPropertyImplementation(Isolate* isolate,
+ Handle<JSObject> object,
+ Handle<Name> key) {
+ if (JSReceiver::HasOwnProperty(object, key)) {
return isolate->heap()->true_value();
}
// Handle hidden prototypes. If there's a hidden prototype above this thing
@@ -5598,20 +5685,20 @@ static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
Handle<Object> proto(object->GetPrototype(), isolate);
if (proto->IsJSObject() &&
Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
- return HasLocalPropertyImplementation(isolate,
- Handle<JSObject>::cast(proto),
- key);
+ return HasOwnPropertyImplementation(isolate,
+ Handle<JSObject>::cast(proto),
+ key);
}
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->false_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
+RUNTIME_FUNCTION(Runtime_HasOwnProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0)
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
- Handle<Object> object = args.at<Object>(0);
uint32_t index;
const bool key_is_array_index = key->AsArrayIndex(&index);
@@ -5626,7 +5713,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
ASSERT(!isolate->has_scheduled_exception());
return isolate->heap()->true_value();
} else {
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
}
Map* map = js_obj->map();
if (!key_is_array_index &&
@@ -5635,9 +5722,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
return isolate->heap()->false_value();
}
// Slow case.
- return HasLocalPropertyImplementation(isolate,
- Handle<JSObject>(js_obj),
- Handle<Name>(key));
+ return HasOwnPropertyImplementation(isolate,
+ Handle<JSObject>(js_obj),
+ Handle<Name>(key));
} else if (object->IsString() && key_is_array_index) {
// Well, there is one exception: Handle [] on strings.
Handle<String> string = Handle<String>::cast(object);
@@ -5649,42 +5736,41 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
+RUNTIME_FUNCTION(Runtime_HasProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
bool result = JSReceiver::HasProperty(receiver, key);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
- if (isolate->has_pending_exception()) return Failure::Exception();
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
+RUNTIME_FUNCTION(Runtime_HasElement) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_SMI_ARG_CHECKED(index, 1);
bool result = JSReceiver::HasElement(receiver, index);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
- if (isolate->has_pending_exception()) return Failure::Exception();
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->ToBoolean(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(JSObject, object, 0);
- CONVERT_ARG_CHECKED(Name, key, 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
- PropertyAttributes att = object->GetLocalPropertyAttribute(key);
+ PropertyAttributes att = JSReceiver::GetOwnPropertyAttributes(object, key);
if (att == ABSENT || (att & DONT_ENUM) != 0) {
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->false_value();
}
ASSERT(!isolate->has_scheduled_exception());
@@ -5692,14 +5778,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
+RUNTIME_FUNCTION(Runtime_GetPropertyNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
- bool threw = false;
- Handle<JSArray> result = GetKeysFor(object, &threw);
- if (threw) return Failure::Exception();
- return *result;
+ Handle<JSArray> result;
+
+ isolate->counters()->for_in()->Increment();
+ Handle<FixedArray> elements;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, elements,
+ JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
+ return *isolate->factory()->NewJSArrayWithElements(elements);
}
@@ -5708,7 +5798,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
// all enumerable properties of the object and its prototypes
// have none, the map of the object. This is used to speed up
// the check for deletions during a for-in.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
+RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -5718,10 +5808,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
HandleScope scope(isolate);
Handle<JSReceiver> object(raw_object);
- bool threw = false;
- Handle<FixedArray> content =
- GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
- if (threw) return Failure::Exception();
+ Handle<FixedArray> content;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, content,
+ JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
// Test again, since cache may have been built by preceding call.
if (object->IsSimpleEnum()) return object->map();
@@ -5730,10 +5820,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
}
-// Find the length of the prototype chain that is to to handled as one. If a
+// Find the length of the prototype chain that is to be handled as one. If a
// prototype object is hidden it is to be viewed as part of the the object it
// is prototype for.
-static int LocalPrototypeChainLength(JSObject* obj) {
+static int OwnPrototypeChainLength(JSObject* obj) {
int count = 1;
Object* proto = obj->GetPrototype();
while (proto->IsJSObject() &&
@@ -5745,53 +5835,52 @@ static int LocalPrototypeChainLength(JSObject* obj) {
}
-// Return the names of the local named properties.
+// Return the names of the own named properties.
// args[0]: object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
+// args[1]: PropertyAttributes as int
+RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
if (!args[0]->IsJSObject()) {
return isolate->heap()->undefined_value();
}
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
- CONVERT_BOOLEAN_ARG_CHECKED(include_symbols, 1);
- PropertyAttributes filter = include_symbols ? NONE : SYMBOLIC;
+ CONVERT_SMI_ARG_CHECKED(filter_value, 1);
+ PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
// Skip the global proxy as it has no properties and always delegates to the
// real global object.
if (obj->IsJSGlobalProxy()) {
// Only collect names if access is permitted.
if (obj->IsAccessCheckNeeded() &&
- !isolate->MayNamedAccess(*obj,
- isolate->heap()->undefined_value(),
- v8::ACCESS_KEYS)) {
- isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ !isolate->MayNamedAccess(
+ obj, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
+ isolate->ReportFailedAccessCheck(obj, v8::ACCESS_KEYS);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return *isolate->factory()->NewJSArray(0);
}
obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
}
// Find the number of objects making up this.
- int length = LocalPrototypeChainLength(*obj);
+ int length = OwnPrototypeChainLength(*obj);
- // Find the number of local properties for each of the objects.
- ScopedVector<int> local_property_count(length);
+ // Find the number of own properties for each of the objects.
+ ScopedVector<int> own_property_count(length);
int total_property_count = 0;
Handle<JSObject> jsproto = obj;
for (int i = 0; i < length; i++) {
// Only collect names if access is permitted.
if (jsproto->IsAccessCheckNeeded() &&
- !isolate->MayNamedAccess(*jsproto,
- isolate->heap()->undefined_value(),
- v8::ACCESS_KEYS)) {
- isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ !isolate->MayNamedAccess(
+ jsproto, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
+ isolate->ReportFailedAccessCheck(jsproto, v8::ACCESS_KEYS);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return *isolate->factory()->NewJSArray(0);
}
int n;
- n = jsproto->NumberOfLocalProperties(filter);
- local_property_count[i] = n;
+ n = jsproto->NumberOfOwnProperties(filter);
+ own_property_count[i] = n;
total_property_count += n;
if (i < length - 1) {
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
@@ -5804,41 +5893,66 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
// Get the property names.
jsproto = obj;
- int proto_with_hidden_properties = 0;
int next_copy_index = 0;
+ int hidden_strings = 0;
for (int i = 0; i < length; i++) {
- jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
- next_copy_index += local_property_count[i];
- if (jsproto->HasHiddenProperties()) {
- proto_with_hidden_properties++;
+ jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
+ if (i > 0) {
+ // Names from hidden prototypes may already have been added
+ // for inherited function template instances. Count the duplicates
+ // and stub them out; the final copy pass at the end ignores holes.
+ for (int j = next_copy_index;
+ j < next_copy_index + own_property_count[i];
+ j++) {
+ Object* name_from_hidden_proto = names->get(j);
+ for (int k = 0; k < next_copy_index; k++) {
+ if (names->get(k) != isolate->heap()->hidden_string()) {
+ Object* name = names->get(k);
+ if (name_from_hidden_proto == name) {
+ names->set(j, isolate->heap()->hidden_string());
+ hidden_strings++;
+ break;
+ }
+ }
+ }
+ }
+ }
+ next_copy_index += own_property_count[i];
+
+ // Hidden properties only show up if the filter does not skip strings.
+ if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) {
+ hidden_strings++;
}
if (i < length - 1) {
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
}
}
- // Filter out name of hidden properties object.
- if (proto_with_hidden_properties > 0) {
+ // Filter out name of hidden properties object and
+ // hidden prototype duplicates.
+ if (hidden_strings > 0) {
Handle<FixedArray> old_names = names;
names = isolate->factory()->NewFixedArray(
- names->length() - proto_with_hidden_properties);
+ names->length() - hidden_strings);
int dest_pos = 0;
for (int i = 0; i < total_property_count; i++) {
Object* name = old_names->get(i);
if (name == isolate->heap()->hidden_string()) {
+ hidden_strings--;
continue;
}
names->set(dest_pos++, name);
}
+ ASSERT_EQ(0, hidden_strings);
}
return *isolate->factory()->NewJSArrayWithElements(names);
}
-// Return the names of the local indexed properties.
+// Return the names of the own indexed properties.
// args[0]: object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
+RUNTIME_FUNCTION(Runtime_GetOwnElementNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
if (!args[0]->IsJSObject()) {
@@ -5846,16 +5960,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
}
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
- int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
+ int n = obj->NumberOfOwnElements(static_cast<PropertyAttributes>(NONE));
Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
- obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
+ obj->GetOwnElementKeys(*names, static_cast<PropertyAttributes>(NONE));
return *isolate->factory()->NewJSArrayWithElements(names);
}
// Return information on whether an object has a named or indexed interceptor.
// args[0]: object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
+RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
if (!args[0]->IsJSObject()) {
@@ -5873,14 +5987,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
// Return property names from named interceptor.
// args[0]: object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
+RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
if (obj->HasNamedInterceptor()) {
- v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
- if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+ Handle<JSObject> result;
+ if (JSObject::GetKeysForNamedInterceptor(obj, obj).ToHandle(&result)) {
+ return *result;
+ }
}
return isolate->heap()->undefined_value();
}
@@ -5888,32 +6004,34 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
// Return element names from indexed interceptor.
// args[0]: object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
+RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
if (obj->HasIndexedInterceptor()) {
- v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
- if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+ Handle<JSObject> result;
+ if (JSObject::GetKeysForIndexedInterceptor(obj, obj).ToHandle(&result)) {
+ return *result;
+ }
}
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
+RUNTIME_FUNCTION(Runtime_OwnKeys) {
HandleScope scope(isolate);
- ASSERT_EQ(args.length(), 1);
+ ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
Handle<JSObject> object(raw_object);
if (object->IsJSGlobalProxy()) {
// Do access checks before going to the global object.
if (object->IsAccessCheckNeeded() &&
- !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
- v8::ACCESS_KEYS)) {
- isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
- RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+ !isolate->MayNamedAccess(
+ object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
+ isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return *isolate->factory()->NewJSArray(0);
}
@@ -5923,10 +6041,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
object = Handle<JSObject>::cast(proto);
}
- bool threw = false;
- Handle<FixedArray> contents =
- GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
- if (threw) return Failure::Exception();
+ Handle<FixedArray> contents;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, contents,
+ JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY));
// Some fast paths through GetKeysInFixedArrayFor reuse a cached
// property array and since the result is mutable we have to create
@@ -5950,9 +6068,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
+RUNTIME_FUNCTION(Runtime_GetArgumentsProperty) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
// Compute the frame holding the arguments.
JavaScriptFrameIterator it(isolate);
@@ -5965,22 +6084,25 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
// Try to convert the key to an index. If successful and within
// index return the the argument from the frame.
uint32_t index;
- if (args[0]->ToArrayIndex(&index) && index < n) {
+ if (raw_key->ToArrayIndex(&index) && index < n) {
return frame->GetParameter(index);
}
- if (args[0]->IsSymbol()) {
+ HandleScope scope(isolate);
+ if (raw_key->IsSymbol()) {
// Lookup in the initial Object.prototype object.
- return isolate->initial_object_prototype()->GetProperty(
- Symbol::cast(args[0]));
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Object::GetProperty(isolate->initial_object_prototype(),
+ Handle<Symbol>::cast(raw_key)));
+ return *result;
}
// Convert the key to a string.
- HandleScope scope(isolate);
- bool exception = false;
- Handle<Object> converted =
- Execution::ToString(isolate, args.at<Object>(0), &exception);
- if (exception) return Failure::Exception();
+ Handle<Object> converted;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, raw_key));
Handle<String> key = Handle<String>::cast(converted);
// Try to convert the string key into an array index.
@@ -5988,15 +6110,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
if (index < n) {
return frame->GetParameter(index);
} else {
- return isolate->initial_object_prototype()->GetElement(isolate, index);
+ Handle<Object> initial_prototype(isolate->initial_object_prototype());
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Object::GetElement(isolate, initial_prototype, index));
+ return *result;
}
}
// Handle special arguments properties.
- if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
- if (key->Equals(isolate->heap()->callee_string())) {
+ if (String::Equals(isolate->factory()->length_string(), key)) {
+ return Smi::FromInt(n);
+ }
+ if (String::Equals(isolate->factory()->callee_string(), key)) {
JSFunction* function = frame->function();
- if (!function->shared()->is_classic_mode()) {
+ if (function->shared()->strict_mode() == STRICT) {
return isolate->Throw(*isolate->factory()->NewTypeError(
"strict_arguments_callee", HandleVector<Object>(NULL, 0)));
}
@@ -6004,11 +6133,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
}
// Lookup in the initial Object.prototype object.
- return isolate->initial_object_prototype()->GetProperty(*key);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Object::GetProperty(isolate->initial_object_prototype(), key));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
+RUNTIME_FUNCTION(Runtime_ToFastProperties) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
@@ -6019,20 +6152,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
+RUNTIME_FUNCTION(Runtime_ToBool) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
+ CONVERT_ARG_CHECKED(Object, object, 0);
- return isolate->heap()->ToBoolean(args[0]->BooleanValue());
+ return isolate->heap()->ToBoolean(object->BooleanValue());
}
// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
// Possible optimizations: put the type string into the oddballs.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
+RUNTIME_FUNCTION(Runtime_Typeof) {
SealHandleScope shs(isolate);
-
- Object* obj = args[0];
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_CHECKED(Object, obj, 0);
if (obj->IsNumber()) return isolate->heap()->number_string();
HeapObject* heap_obj = HeapObject::cast(obj);
@@ -6093,18 +6227,19 @@ static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_StringToNumber) {
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(String, subject, 0);
- subject->TryFlatten();
+ CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
+ subject = String::Flatten(subject);
// Fast case: short integer or some sorts of junk values.
- int len = subject->length();
if (subject->IsSeqOneByteString()) {
+ int len = subject->length();
if (len == 0) return Smi::FromInt(0);
- uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
+ DisallowHeapAllocation no_gc;
+ uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
bool minus = (data[0] == '-');
int start_pos = (minus ? 1 : 0);
@@ -6112,15 +6247,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
return isolate->heap()->nan_value();
} else if (data[start_pos] > '9') {
// Fast check for a junk value. A valid string may start from a
- // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
- // the 'I' character ('Infinity'). All of that have codes not greater than
- // '9' except 'I' and &nbsp;.
+ // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
+ // or the 'I' character ('Infinity'). All of that have codes not greater
+ // than '9' except 'I' and &nbsp;.
if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
return isolate->heap()->nan_value();
}
} else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
- // The maximal/minimal smi has 10 digits. If the string has less digits we
- // know it will fit into the smi-data type.
+ // The maximal/minimal smi has 10 digits. If the string has less digits
+ // we know it will fit into the smi-data type.
int d = ParseDecimalInteger(data, start_pos, len);
if (minus) {
if (d == 0) return isolate->heap()->minus_zero_value();
@@ -6149,144 +6284,173 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
// Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
flags |= ALLOW_OCTAL | ALLOW_BINARY;
}
- return isolate->heap()->NumberFromDouble(
- StringToDouble(isolate->unicode_cache(), subject, flags));
+
+ return *isolate->factory()->NewNumber(StringToDouble(
+ isolate->unicode_cache(), *subject, flags));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NewString) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(length, 0);
CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
if (length == 0) return isolate->heap()->empty_string();
+ Handle<String> result;
if (is_one_byte) {
- return isolate->heap()->AllocateRawOneByteString(length);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, isolate->factory()->NewRawOneByteString(length));
} else {
- return isolate->heap()->AllocateRawTwoByteString(length);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, isolate->factory()->NewRawTwoByteString(length));
}
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
+RUNTIME_FUNCTION(Runtime_TruncateString) {
HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
CONVERT_SMI_ARG_CHECKED(new_length, 1);
+ RUNTIME_ASSERT(new_length >= 0);
return *SeqString::Truncate(string, new_length);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
+RUNTIME_FUNCTION(Runtime_URIEscape) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
- Handle<String> string = FlattenGetString(source);
+ Handle<String> string = String::Flatten(source);
ASSERT(string->IsFlat());
- Handle<String> result = string->IsOneByteRepresentationUnderneath()
- ? URIEscape::Escape<uint8_t>(isolate, source)
- : URIEscape::Escape<uc16>(isolate, source);
- if (result.is_null()) return Failure::OutOfMemoryException(0x12);
+ Handle<String> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ string->IsOneByteRepresentationUnderneath()
+ ? URIEscape::Escape<uint8_t>(isolate, source)
+ : URIEscape::Escape<uc16>(isolate, source));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
+RUNTIME_FUNCTION(Runtime_URIUnescape) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
- Handle<String> string = FlattenGetString(source);
+ Handle<String> string = String::Flatten(source);
ASSERT(string->IsFlat());
- return string->IsOneByteRepresentationUnderneath()
- ? *URIUnescape::Unescape<uint8_t>(isolate, source)
- : *URIUnescape::Unescape<uc16>(isolate, source);
+ Handle<String> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ string->IsOneByteRepresentationUnderneath()
+ ? URIUnescape::Unescape<uint8_t>(isolate, source)
+ : URIUnescape::Unescape<uc16>(isolate, source));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
+RUNTIME_FUNCTION(Runtime_QuoteJSONString) {
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
ASSERT(args.length() == 1);
- return BasicJsonStringifier::StringifyString(isolate, string);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, BasicJsonStringifier::StringifyString(isolate, string));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
+RUNTIME_FUNCTION(Runtime_BasicJSONStringify) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
BasicJsonStringifier stringifier(isolate);
- return stringifier.Stringify(Handle<Object>(args[0], isolate));
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, stringifier.Stringify(object));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_StringParseInt) {
+ HandleScope handle_scope(isolate);
+ ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
+ CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]);
+ RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
- CONVERT_ARG_CHECKED(String, s, 0);
- CONVERT_SMI_ARG_CHECKED(radix, 1);
+ subject = String::Flatten(subject);
+ double value;
- s->TryFlatten();
+ { DisallowHeapAllocation no_gc;
+ String::FlatContent flat = subject->GetFlatContent();
- RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
- double value = StringToInt(isolate->unicode_cache(), s, radix);
- return isolate->heap()->NumberFromDouble(value);
+ // ECMA-262 section 15.1.2.3, empty string is NaN
+ if (flat.IsAscii()) {
+ value = StringToInt(
+ isolate->unicode_cache(), flat.ToOneByteVector(), radix);
+ } else {
+ value = StringToInt(
+ isolate->unicode_cache(), flat.ToUC16Vector(), radix);
+ }
+ }
+
+ return *isolate->factory()->NewNumber(value);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
- SealHandleScope shs(isolate);
- CONVERT_ARG_CHECKED(String, str, 0);
+RUNTIME_FUNCTION(Runtime_StringParseFloat) {
+ HandleScope shs(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
- // ECMA-262 section 15.1.2.3, empty string is NaN
- double value = StringToDouble(isolate->unicode_cache(),
- str, ALLOW_TRAILING_JUNK, OS::nan_value());
+ subject = String::Flatten(subject);
+ double value = StringToDouble(
+ isolate->unicode_cache(), *subject, ALLOW_TRAILING_JUNK, OS::nan_value());
- // Create a number object from the value.
- return isolate->heap()->NumberFromDouble(value);
+ return *isolate->factory()->NewNumber(value);
+}
+
+
+static inline bool ToUpperOverflows(uc32 character) {
+ // y with umlauts and the micro sign are the only characters that stop
+ // fitting into one-byte when converting to uppercase.
+ static const uc32 yuml_code = 0xff;
+ static const uc32 micro_code = 0xb5;
+ return (character == yuml_code || character == micro_code);
}
template <class Converter>
-MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
+MUST_USE_RESULT static Object* ConvertCaseHelper(
Isolate* isolate,
- String* s,
- String::Encoding result_encoding,
- int length,
- int input_string_length,
+ String* string,
+ SeqString* result,
+ int result_length,
unibrow::Mapping<Converter, 128>* mapping) {
+ DisallowHeapAllocation no_gc;
// We try this twice, once with the assumption that the result is no longer
// than the input and, if that assumption breaks, again with the exact
// length. This may not be pretty, but it is nicer than what was here before
// and I hereby claim my vaffel-is.
//
- // Allocate the resulting string.
- //
// NOTE: This assumes that the upper/lower case of an ASCII
// character is also ASCII. This is currently the case, but it
// might break in the future if we implement more context and locale
// dependent upper/lower conversions.
- Object* o;
- { MaybeObject* maybe_o = result_encoding == String::ONE_BYTE_ENCODING
- ? isolate->heap()->AllocateRawOneByteString(length)
- : isolate->heap()->AllocateRawTwoByteString(length);
- if (!maybe_o->ToObject(&o)) return maybe_o;
- }
- String* result = String::cast(o);
bool has_changed_character = false;
- DisallowHeapAllocation no_gc;
-
// Convert all characters to upper case, assuming that they will fit
// in the buffer
Access<ConsStringIteratorOp> op(
isolate->runtime_state()->string_iterator());
- StringCharacterStream stream(s, op.value());
+ StringCharacterStream stream(string, op.value());
unibrow::uchar chars[Converter::kMaxWidth];
// We can assume that the string is not empty
uc32 current = stream.GetNext();
- // y with umlauts is the only character that stops fitting into one-byte
- // when converting to uppercase.
- static const uc32 yuml_code = 0xff;
- bool ignore_yuml = result->IsSeqTwoByteString() || Converter::kIsToLower;
- for (int i = 0; i < length;) {
+ bool ignore_overflow = Converter::kIsToLower || result->IsSeqTwoByteString();
+ for (int i = 0; i < result_length;) {
bool has_next = stream.HasMore();
uc32 next = has_next ? stream.GetNext() : 0;
int char_length = mapping->get(current, next, chars);
@@ -6294,14 +6458,15 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
// The case conversion of this character is the character itself.
result->Set(i, current);
i++;
- } else if (char_length == 1 && (ignore_yuml || current != yuml_code)) {
+ } else if (char_length == 1 &&
+ (ignore_overflow || !ToUpperOverflows(current))) {
// Common case: converting the letter resulted in one character.
ASSERT(static_cast<uc32>(chars[0]) != current);
result->Set(i, chars[0]);
has_changed_character = true;
i++;
- } else if (length == input_string_length) {
- bool found_yuml = (current == yuml_code);
+ } else if (result_length == string->length()) {
+ bool overflows = ToUpperOverflows(current);
// We've assumed that the result would be as long as the
// input but here is a character that converts to several
// characters. No matter, we calculate the exact length
@@ -6321,7 +6486,7 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
int current_length = i + char_length + next_length;
while (stream.HasMore()) {
current = stream.GetNext();
- found_yuml |= (current == yuml_code);
+ overflows |= ToUpperOverflows(current);
// NOTE: we use 0 as the next character here because, while
// the next character may affect what a character converts to,
// it does not in any case affect the length of what it convert
@@ -6329,15 +6494,15 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
int char_length = mapping->get(current, 0, chars);
if (char_length == 0) char_length = 1;
current_length += char_length;
- if (current_length > Smi::kMaxValue) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x13);
+ if (current_length > String::kMaxLength) {
+ AllowHeapAllocation allocate_error_and_return;
+ return isolate->ThrowInvalidStringLength();
}
}
// Try again with the real length. Return signed if we need
- // to allocate a two-byte string for y-umlaut to uppercase.
- return (found_yuml && !ignore_yuml) ? Smi::FromInt(-current_length)
- : Smi::FromInt(current_length);
+ // to allocate a two-byte string for to uppercase.
+ return (overflows && !ignore_overflow) ? Smi::FromInt(-current_length)
+ : Smi::FromInt(current_length);
} else {
for (int j = 0; j < char_length; j++) {
result->Set(i, chars[j]);
@@ -6354,7 +6519,7 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
// we simple return the result and let the converted string
// become garbage; there is no reason to keep two identical strings
// alive.
- return s;
+ return string;
}
}
@@ -6385,7 +6550,7 @@ static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
#ifdef DEBUG
static bool CheckFastAsciiConvert(char* dst,
- char* src,
+ const char* src,
int length,
bool changed,
bool is_to_lower) {
@@ -6408,12 +6573,12 @@ static bool CheckFastAsciiConvert(char* dst,
template<class Converter>
static bool FastAsciiConvert(char* dst,
- char* src,
+ const char* src,
int length,
bool* changed_out) {
#ifdef DEBUG
char* saved_dst = dst;
- char* saved_src = src;
+ const char* saved_src = src;
#endif
DisallowHeapAllocation no_gc;
// We rely on the distance between upper and lower case letters
@@ -6424,12 +6589,12 @@ static bool FastAsciiConvert(char* dst,
static const char hi = Converter::kIsToLower ? 'Z' + 1 : 'z' + 1;
bool changed = false;
uintptr_t or_acc = 0;
- char* const limit = src + length;
+ const char* const limit = src + length;
#ifdef V8_HOST_CAN_READ_UNALIGNED
// Process the prefix of the input that requires no conversion one
// (machine) word at a time.
while (src <= limit - sizeof(uintptr_t)) {
- uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
+ const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
or_acc |= w;
if (AsciiRangeMask(w, lo, hi) != 0) {
changed = true;
@@ -6442,7 +6607,7 @@ static bool FastAsciiConvert(char* dst,
// Process the remainder of the input performing conversion when
// required one word at a time.
while (src <= limit - sizeof(uintptr_t)) {
- uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
+ const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
or_acc |= w;
uintptr_t m = AsciiRangeMask(w, lo, hi);
// The mask has high (7th) bit set in every byte that needs
@@ -6481,17 +6646,14 @@ static bool FastAsciiConvert(char* dst,
template <class Converter>
-MUST_USE_RESULT static MaybeObject* ConvertCase(
- Arguments args,
+MUST_USE_RESULT static Object* ConvertCase(
+ Handle<String> s,
Isolate* isolate,
unibrow::Mapping<Converter, 128>* mapping) {
- SealHandleScope shs(isolate);
- CONVERT_ARG_CHECKED(String, s, 0);
- s = s->TryFlattenGetString();
-
- const int length = s->length();
+ s = String::Flatten(s);
+ int length = s->length();
// Assume that the string is not empty; we need this assumption later
- if (length == 0) return s;
+ if (length == 0) return *s;
// Simpler handling of ASCII strings.
//
@@ -6499,96 +6661,105 @@ MUST_USE_RESULT static MaybeObject* ConvertCase(
// character is also ASCII. This is currently the case, but it
// might break in the future if we implement more context and locale
// dependent upper/lower conversions.
- if (s->IsSeqOneByteString()) {
- Object* o;
- { MaybeObject* maybe_o = isolate->heap()->AllocateRawOneByteString(length);
- if (!maybe_o->ToObject(&o)) return maybe_o;
- }
- SeqOneByteString* result = SeqOneByteString::cast(o);
- bool has_changed_character;
+ if (s->IsOneByteRepresentationUnderneath()) {
+ // Same length as input.
+ Handle<SeqOneByteString> result =
+ isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
+ DisallowHeapAllocation no_gc;
+ String::FlatContent flat_content = s->GetFlatContent();
+ ASSERT(flat_content.IsFlat());
+ bool has_changed_character = false;
bool is_ascii = FastAsciiConvert<Converter>(
reinterpret_cast<char*>(result->GetChars()),
- reinterpret_cast<char*>(SeqOneByteString::cast(s)->GetChars()),
+ reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()),
length,
&has_changed_character);
// If not ASCII, we discard the result and take the 2 byte path.
- if (is_ascii) {
- return has_changed_character ? result : s;
- }
+ if (is_ascii) return has_changed_character ? *result : *s;
}
- String::Encoding result_encoding = s->IsOneByteRepresentation()
- ? String::ONE_BYTE_ENCODING : String::TWO_BYTE_ENCODING;
- Object* answer;
- { MaybeObject* maybe_answer = ConvertCaseHelper(
- isolate, s, result_encoding, length, length, mapping);
- if (!maybe_answer->ToObject(&answer)) return maybe_answer;
- }
- if (answer->IsSmi()) {
- int new_length = Smi::cast(answer)->value();
- if (new_length < 0) {
- result_encoding = String::TWO_BYTE_ENCODING;
- new_length = -new_length;
- }
- MaybeObject* maybe_answer = ConvertCaseHelper(
- isolate, s, result_encoding, new_length, length, mapping);
- if (!maybe_answer->ToObject(&answer)) return maybe_answer;
+ Handle<SeqString> result; // Same length as input.
+ if (s->IsOneByteRepresentation()) {
+ result = isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
+ } else {
+ result = isolate->factory()->NewRawTwoByteString(length).ToHandleChecked();
}
- return answer;
-}
+ Object* answer = ConvertCaseHelper(isolate, *s, *result, length, mapping);
+ if (answer->IsException() || answer->IsString()) return answer;
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
- return ConvertCase(
- args, isolate, isolate->runtime_state()->to_lower_mapping());
+ ASSERT(answer->IsSmi());
+ length = Smi::cast(answer)->value();
+ if (s->IsOneByteRepresentation() && length > 0) {
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, isolate->factory()->NewRawOneByteString(length));
+ } else {
+ if (length < 0) length = -length;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, isolate->factory()->NewRawTwoByteString(length));
+ }
+ return ConvertCaseHelper(isolate, *s, *result, length, mapping);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
+RUNTIME_FUNCTION(Runtime_StringToLowerCase) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
return ConvertCase(
- args, isolate, isolate->runtime_state()->to_upper_mapping());
+ s, isolate, isolate->runtime_state()->to_lower_mapping());
}
-static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
- return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
+RUNTIME_FUNCTION(Runtime_StringToUpperCase) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
+ return ConvertCase(
+ s, isolate, isolate->runtime_state()->to_upper_mapping());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_StringTrim) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
- CONVERT_ARG_CHECKED(String, s, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
- s->TryFlatten();
- int length = s->length();
+ string = String::Flatten(string);
+ int length = string->length();
int left = 0;
+ UnicodeCache* unicode_cache = isolate->unicode_cache();
if (trimLeft) {
- while (left < length && IsTrimWhiteSpace(s->Get(left))) {
+ while (left < length &&
+ unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
left++;
}
}
int right = length;
if (trimRight) {
- while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
+ while (right > left &&
+ unicode_cache->IsWhiteSpaceOrLineTerminator(
+ string->Get(right - 1))) {
right--;
}
}
- return s->SubString(left, right);
+
+ return *isolate->factory()->NewSubString(string, left, right);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
+RUNTIME_FUNCTION(Runtime_StringSplit) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
+ RUNTIME_ASSERT(limit > 0);
int subject_length = subject->length();
int pattern_length = pattern->length();
@@ -6614,7 +6785,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
// isn't empty, we can never create more parts than ~half the length
// of the subject.
- if (!subject->IsFlat()) FlattenString(subject);
+ subject = String::Flatten(subject);
+ pattern = String::Flatten(pattern);
static const int kMaxInitialListCapacity = 16;
@@ -6623,7 +6795,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
// Find (up to limit) indices of separator and end-of-string in subject
int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
ZoneList<int> indices(initial_capacity, zone_scope.zone());
- if (!pattern->IsFlat()) FlattenString(pattern);
FindStringIndicesDispatch(isolate, *subject, *pattern,
&indices, limit, zone_scope.zone());
@@ -6661,10 +6832,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
if (limit == 0xffffffffu) {
if (result->HasFastObjectElements()) {
- RegExpResultsCache::Enter(isolate->heap(),
- *subject,
- *pattern,
- *elements,
+ RegExpResultsCache::Enter(isolate,
+ subject,
+ pattern,
+ elements,
RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
}
}
@@ -6708,25 +6879,21 @@ static int CopyCachedAsciiCharsToArray(Heap* heap,
// Converts a String to JSArray.
// For example, "foo" => ["f", "o", "o"].
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
+RUNTIME_FUNCTION(Runtime_StringToArray) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
- s = FlattenGetString(s);
+ s = String::Flatten(s);
const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
Handle<FixedArray> elements;
int position = 0;
if (s->IsFlat() && s->IsOneByteRepresentation()) {
// Try using cached chars where possible.
- Object* obj;
- { MaybeObject* maybe_obj =
- isolate->heap()->AllocateUninitializedFixedArray(length);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
+ elements = isolate->factory()->NewUninitializedFixedArray(length);
+
DisallowHeapAllocation no_gc;
String::FlatContent content = s->GetFlatContent();
if (content.IsAscii()) {
@@ -6747,7 +6914,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
}
for (int i = position; i < length; ++i) {
Handle<Object> str =
- LookupSingleCharacterStringFromCode(isolate, s->Get(i));
+ isolate->factory()->LookupSingleCharacterStringFromCode(s->Get(i));
elements->set(i, *str);
}
@@ -6761,11 +6928,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NewStringWrapper) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(String, value, 0);
- return value->ToObject(isolate);
+ CONVERT_ARG_HANDLE_CHECKED(String, value, 0);
+ return *Object::ToObject(isolate, value).ToHandleChecked();
}
@@ -6776,110 +6943,70 @@ bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
-
- Object* number = args[0];
- RUNTIME_ASSERT(number->IsNumber());
-
- return isolate->heap()->NumberToString(number);
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_NumberToString) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
- Object* number = args[0];
- RUNTIME_ASSERT(number->IsNumber());
-
- return isolate->heap()->NumberToString(
- number, false, isolate->heap()->GetPretenureMode());
+ return *isolate->factory()->NumberToString(number);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_NumberToStringSkipCache) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
- CONVERT_DOUBLE_ARG_CHECKED(number, 0);
-
- // We do not include 0 so that we don't have to treat +0 / -0 cases.
- if (number > 0 && number <= Smi::kMaxValue) {
- return Smi::FromInt(static_cast<int>(number));
- }
- return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
+ return *isolate->factory()->NumberToString(number, false);
}
-// ES6 draft 9.1.11
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPositiveInteger) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToInteger) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(number, 0);
-
- // We do not include 0 so that we don't have to treat +0 / -0 cases.
- if (number > 0 && number <= Smi::kMaxValue) {
- return Smi::FromInt(static_cast<int>(number));
- }
- if (number <= 0) {
- return Smi::FromInt(0);
- }
- return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
+ return *isolate->factory()->NewNumber(DoubleToInteger(number));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(number, 0);
-
- // We do not include 0 so that we don't have to treat +0 / -0 cases.
- if (number > 0 && number <= Smi::kMaxValue) {
- return Smi::FromInt(static_cast<int>(number));
- }
-
double double_value = DoubleToInteger(number);
// Map both -0 and +0 to +0.
if (double_value == 0) double_value = 0;
- return isolate->heap()->NumberFromDouble(double_value);
+ return *isolate->factory()->NewNumber(double_value);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToJSUint32) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
- return isolate->heap()->NumberFromUint32(number);
+ return *isolate->factory()->NewNumberFromUint(number);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberToJSInt32) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(number, 0);
-
- // We do not include 0 so that we don't have to treat +0 / -0 cases.
- if (number > 0 && number <= Smi::kMaxValue) {
- return Smi::FromInt(static_cast<int>(number));
- }
- return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
+ return *isolate->factory()->NewNumberFromInt(DoubleToInt32(number));
}
// Converts a Number to a Smi, if possible. Returns NaN if the number is not
// a small integer.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
+RUNTIME_FUNCTION(RuntimeHidden_NumberToSmi) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
-
- Object* obj = args[0];
+ CONVERT_ARG_CHECKED(Object, obj, 0);
if (obj->IsSmi()) {
return obj;
}
@@ -6894,100 +7021,92 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_AllocateHeapNumber) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 0);
- return isolate->heap()->AllocateHeapNumber(0);
+ return *isolate->factory()->NewHeapNumber(0);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberAdd) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- return isolate->heap()->NumberFromDouble(x + y);
+ return *isolate->factory()->NewNumber(x + y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberSub) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- return isolate->heap()->NumberFromDouble(x - y);
+ return *isolate->factory()->NewNumber(x - y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberMul) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- return isolate->heap()->NumberFromDouble(x * y);
+ return *isolate->factory()->NewNumber(x * y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberUnaryMinus) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->heap()->NumberFromDouble(-x);
+ return *isolate->factory()->NewNumber(-x);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 0);
-
- return isolate->heap()->NumberFromDouble(9876543210.0);
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberDiv) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- return isolate->heap()->NumberFromDouble(x / y);
+ return *isolate->factory()->NewNumber(x / y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberMod) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
-
- x = modulo(x, y);
- // NumberFromDouble may return a Smi instead of a Number object
- return isolate->heap()->NumberFromDouble(x);
+ return *isolate->factory()->NewNumber(modulo(x, y));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberImul) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x * y);
+ return *isolate->factory()->NewNumberFromInt(x * y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_StringAdd) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(String, str1, 0);
- CONVERT_ARG_CHECKED(String, str2, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
isolate->counters()->string_add_runtime()->Increment();
- return isolate->heap()->AllocateConsString(str1, str2);
+ Handle<String> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, isolate->factory()->NewConsString(str1, str2));
+ return *result;
}
@@ -6996,6 +7115,7 @@ static inline void StringBuilderConcatHelper(String* special,
sinkchar* sink,
FixedArray* fixed_array,
int array_length) {
+ DisallowHeapAllocation no_gc;
int position = 0;
for (int i = 0; i < array_length; i++) {
Object* element = fixed_array->get(i);
@@ -7030,39 +7150,13 @@ static inline void StringBuilderConcatHelper(String* special,
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 3);
- CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
- if (!args[1]->IsSmi()) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x14);
- }
- int array_length = args.smi_at(1);
- CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
-
- // This assumption is used by the slice encoding in one or two smis.
- ASSERT(Smi::kMaxValue >= String::kMaxLength);
-
- JSObject::EnsureCanContainHeapObjectElements(array);
-
- int special_length = special->length();
- if (!array->HasFastObjectElements()) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
- FixedArray* fixed_array = FixedArray::cast(array->elements());
- if (fixed_array->length() < array_length) {
- array_length = fixed_array->length();
- }
-
- if (array_length == 0) {
- return isolate->heap()->empty_string();
- } else if (array_length == 1) {
- Object* first = fixed_array->get(0);
- if (first->IsString()) return first;
- }
-
- bool one_byte = special->HasOnlyOneByteChars();
+// Returns the result length of the concatenation.
+// On illegal argument, -1 is returned.
+static inline int StringBuilderConcatLength(int special_length,
+ FixedArray* fixed_array,
+ int array_length,
+ bool* one_byte) {
+ DisallowHeapAllocation no_gc;
int position = 0;
for (int i = 0; i < array_length; i++) {
int increment = 0;
@@ -7081,86 +7175,118 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
len = -smi_value;
// Get the position and check that it is a positive smi.
i++;
- if (i >= array_length) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ if (i >= array_length) return -1;
Object* next_smi = fixed_array->get(i);
- if (!next_smi->IsSmi()) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ if (!next_smi->IsSmi()) return -1;
pos = Smi::cast(next_smi)->value();
- if (pos < 0) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ if (pos < 0) return -1;
}
ASSERT(pos >= 0);
ASSERT(len >= 0);
- if (pos > special_length || len > special_length - pos) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ if (pos > special_length || len > special_length - pos) return -1;
increment = len;
} else if (elt->IsString()) {
String* element = String::cast(elt);
int element_length = element->length();
increment = element_length;
- if (one_byte && !element->HasOnlyOneByteChars()) {
- one_byte = false;
+ if (*one_byte && !element->HasOnlyOneByteChars()) {
+ *one_byte = false;
}
} else {
- ASSERT(!elt->IsTheHole());
- return isolate->Throw(isolate->heap()->illegal_argument_string());
+ return -1;
}
if (increment > String::kMaxLength - position) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x15);
+ return kMaxInt; // Provoke throw on allocation.
}
position += increment;
}
+ return position;
+}
- int length = position;
- Object* object;
- if (one_byte) {
- { MaybeObject* maybe_object =
- isolate->heap()->AllocateRawOneByteString(length);
- if (!maybe_object->ToObject(&object)) return maybe_object;
+RUNTIME_FUNCTION(Runtime_StringBuilderConcat) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 3);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
+ if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
+ CONVERT_SMI_ARG_CHECKED(array_length, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
+
+ size_t actual_array_length = 0;
+ RUNTIME_ASSERT(
+ TryNumberToSize(isolate, array->length(), &actual_array_length));
+ RUNTIME_ASSERT(array_length >= 0);
+ RUNTIME_ASSERT(static_cast<size_t>(array_length) <= actual_array_length);
+
+ // This assumption is used by the slice encoding in one or two smis.
+ ASSERT(Smi::kMaxValue >= String::kMaxLength);
+
+ RUNTIME_ASSERT(array->HasFastElements());
+ JSObject::EnsureCanContainHeapObjectElements(array);
+
+ int special_length = special->length();
+ if (!array->HasFastObjectElements()) {
+ return isolate->Throw(isolate->heap()->illegal_argument_string());
+ }
+
+ int length;
+ bool one_byte = special->HasOnlyOneByteChars();
+
+ { DisallowHeapAllocation no_gc;
+ FixedArray* fixed_array = FixedArray::cast(array->elements());
+ if (fixed_array->length() < array_length) {
+ array_length = fixed_array->length();
}
- SeqOneByteString* answer = SeqOneByteString::cast(object);
+
+ if (array_length == 0) {
+ return isolate->heap()->empty_string();
+ } else if (array_length == 1) {
+ Object* first = fixed_array->get(0);
+ if (first->IsString()) return first;
+ }
+ length = StringBuilderConcatLength(
+ special_length, fixed_array, array_length, &one_byte);
+ }
+
+ if (length == -1) {
+ return isolate->Throw(isolate->heap()->illegal_argument_string());
+ }
+
+ if (one_byte) {
+ Handle<SeqOneByteString> answer;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, answer,
+ isolate->factory()->NewRawOneByteString(length));
StringBuilderConcatHelper(*special,
answer->GetChars(),
- fixed_array,
+ FixedArray::cast(array->elements()),
array_length);
- return answer;
+ return *answer;
} else {
- { MaybeObject* maybe_object =
- isolate->heap()->AllocateRawTwoByteString(length);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- SeqTwoByteString* answer = SeqTwoByteString::cast(object);
+ Handle<SeqTwoByteString> answer;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, answer,
+ isolate->factory()->NewRawTwoByteString(length));
StringBuilderConcatHelper(*special,
answer->GetChars(),
- fixed_array,
+ FixedArray::cast(array->elements()),
array_length);
- return answer;
+ return *answer;
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_StringBuilderJoin) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
- CONVERT_ARG_CHECKED(JSArray, array, 0);
- if (!args[1]->IsSmi()) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x16);
- }
- int array_length = args.smi_at(1);
- CONVERT_ARG_CHECKED(String, separator, 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
+ if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
+ CONVERT_SMI_ARG_CHECKED(array_length, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
+ RUNTIME_ASSERT(array->HasFastObjectElements());
+ RUNTIME_ASSERT(array_length >= 0);
- if (!array->HasFastObjectElements()) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
- FixedArray* fixed_array = FixedArray::cast(array->elements());
+ Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
if (fixed_array->length() < array_length) {
array_length = fixed_array->length();
}
@@ -7169,54 +7295,56 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
return isolate->heap()->empty_string();
} else if (array_length == 1) {
Object* first = fixed_array->get(0);
- if (first->IsString()) return first;
+ RUNTIME_ASSERT(first->IsString());
+ return first;
}
int separator_length = separator->length();
+ RUNTIME_ASSERT(separator_length > 0);
int max_nof_separators =
(String::kMaxLength + separator_length - 1) / separator_length;
if (max_nof_separators < (array_length - 1)) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x17);
+ return isolate->ThrowInvalidStringLength();
}
int length = (array_length - 1) * separator_length;
for (int i = 0; i < array_length; i++) {
Object* element_obj = fixed_array->get(i);
- if (!element_obj->IsString()) {
- // TODO(1161): handle this case.
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ RUNTIME_ASSERT(element_obj->IsString());
String* element = String::cast(element_obj);
int increment = element->length();
if (increment > String::kMaxLength - length) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x18);
+ STATIC_ASSERT(String::kMaxLength < kMaxInt);
+ length = kMaxInt; // Provoke exception;
+ break;
}
length += increment;
}
- Object* object;
- { MaybeObject* maybe_object =
- isolate->heap()->AllocateRawTwoByteString(length);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- SeqTwoByteString* answer = SeqTwoByteString::cast(object);
+ Handle<SeqTwoByteString> answer;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, answer,
+ isolate->factory()->NewRawTwoByteString(length));
+
+ DisallowHeapAllocation no_gc;
uc16* sink = answer->GetChars();
#ifdef DEBUG
uc16* end = sink + length;
#endif
+ RUNTIME_ASSERT(fixed_array->get(0)->IsString());
String* first = String::cast(fixed_array->get(0));
+ String* separator_raw = *separator;
int first_length = first->length();
String::WriteToFlat(first, sink, 0, first_length);
sink += first_length;
for (int i = 1; i < array_length; i++) {
ASSERT(sink + separator_length <= end);
- String::WriteToFlat(separator, sink, 0, separator_length);
+ String::WriteToFlat(separator_raw, sink, 0, separator_length);
sink += separator_length;
+ RUNTIME_ASSERT(fixed_array->get(i)->IsString());
String* element = String::cast(fixed_array->get(i));
int element_length = element->length();
ASSERT(sink + element_length <= end);
@@ -7227,7 +7355,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
// Use %_FastAsciiArrayJoin instead.
ASSERT(!answer->IsOneByteRepresentation());
- return answer;
+ return *answer;
}
template <typename Char>
@@ -7236,6 +7364,7 @@ static void JoinSparseArrayWithSeparator(FixedArray* elements,
uint32_t array_length,
String* separator,
Vector<Char> buffer) {
+ DisallowHeapAllocation no_gc;
int previous_separator_position = 0;
int separator_length = separator->length();
int cursor = 0;
@@ -7271,53 +7400,55 @@ static void JoinSparseArrayWithSeparator(FixedArray* elements,
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
- CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
- RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, elements_array, 0);
CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
- CONVERT_ARG_CHECKED(String, separator, 2);
+ CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
// elements_array is fast-mode JSarray of alternating positions
// (increasing order) and strings.
+ RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
// array_length is length of original array (used to add separators);
// separator is string to put between elements. Assumed to be non-empty.
+ RUNTIME_ASSERT(array_length > 0);
// Find total length of join result.
int string_length = 0;
bool is_ascii = separator->IsOneByteRepresentation();
- int max_string_length;
- if (is_ascii) {
- max_string_length = SeqOneByteString::kMaxLength;
- } else {
- max_string_length = SeqTwoByteString::kMaxLength;
- }
bool overflow = false;
- CONVERT_NUMBER_CHECKED(int, elements_length,
- Int32, elements_array->length());
+ CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length());
+ RUNTIME_ASSERT(elements_length <= elements_array->elements()->length());
RUNTIME_ASSERT((elements_length & 1) == 0); // Even length.
FixedArray* elements = FixedArray::cast(elements_array->elements());
for (int i = 0; i < elements_length; i += 2) {
RUNTIME_ASSERT(elements->get(i)->IsNumber());
+ CONVERT_NUMBER_CHECKED(uint32_t, position, Uint32, elements->get(i));
+ RUNTIME_ASSERT(position < array_length);
RUNTIME_ASSERT(elements->get(i + 1)->IsString());
- String* string = String::cast(elements->get(i + 1));
- int length = string->length();
- if (is_ascii && !string->IsOneByteRepresentation()) {
- is_ascii = false;
- max_string_length = SeqTwoByteString::kMaxLength;
- }
- if (length > max_string_length ||
- max_string_length - length < string_length) {
- overflow = true;
- break;
+ }
+
+ { DisallowHeapAllocation no_gc;
+ for (int i = 0; i < elements_length; i += 2) {
+ String* string = String::cast(elements->get(i + 1));
+ int length = string->length();
+ if (is_ascii && !string->IsOneByteRepresentation()) {
+ is_ascii = false;
+ }
+ if (length > String::kMaxLength ||
+ String::kMaxLength - length < string_length) {
+ overflow = true;
+ break;
+ }
+ string_length += length;
}
- string_length += length;
}
+
int separator_length = separator->length();
if (!overflow && separator_length > 0) {
if (array_length <= 0x7fffffffu) {
int separator_count = static_cast<int>(array_length) - 1;
- int remaining_length = max_string_length - string_length;
+ int remaining_length = String::kMaxLength - string_length;
if ((remaining_length / separator_length) >= separator_count) {
string_length += separator_length * (array_length - 1);
} else {
@@ -7332,102 +7463,98 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
}
}
if (overflow) {
- // Throw OutOfMemory exception for creating too large a string.
- V8::FatalProcessOutOfMemory("Array join result too large.");
+ // Throw an exception if the resulting string is too large. See
+ // https://code.google.com/p/chromium/issues/detail?id=336820
+ // for details.
+ return isolate->ThrowInvalidStringLength();
}
if (is_ascii) {
- MaybeObject* result_allocation =
- isolate->heap()->AllocateRawOneByteString(string_length);
- if (result_allocation->IsFailure()) return result_allocation;
- SeqOneByteString* result_string =
- SeqOneByteString::cast(result_allocation->ToObjectUnchecked());
- JoinSparseArrayWithSeparator<uint8_t>(elements,
- elements_length,
- array_length,
- separator,
- Vector<uint8_t>(
- result_string->GetChars(),
- string_length));
- return result_string;
+ Handle<SeqOneByteString> result = isolate->factory()->NewRawOneByteString(
+ string_length).ToHandleChecked();
+ JoinSparseArrayWithSeparator<uint8_t>(
+ FixedArray::cast(elements_array->elements()),
+ elements_length,
+ array_length,
+ *separator,
+ Vector<uint8_t>(result->GetChars(), string_length));
+ return *result;
} else {
- MaybeObject* result_allocation =
- isolate->heap()->AllocateRawTwoByteString(string_length);
- if (result_allocation->IsFailure()) return result_allocation;
- SeqTwoByteString* result_string =
- SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
- JoinSparseArrayWithSeparator<uc16>(elements,
- elements_length,
- array_length,
- separator,
- Vector<uc16>(result_string->GetChars(),
- string_length));
- return result_string;
+ Handle<SeqTwoByteString> result = isolate->factory()->NewRawTwoByteString(
+ string_length).ToHandleChecked();
+ JoinSparseArrayWithSeparator<uc16>(
+ FixedArray::cast(elements_array->elements()),
+ elements_length,
+ array_length,
+ *separator,
+ Vector<uc16>(result->GetChars(), string_length));
+ return *result;
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberOr) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x | y);
+ return *isolate->factory()->NewNumberFromInt(x | y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberAnd) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x & y);
+ return *isolate->factory()->NewNumberFromInt(x & y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberXor) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x ^ y);
+ return *isolate->factory()->NewNumberFromInt(x ^ y);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberShl) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
+ return *isolate->factory()->NewNumberFromInt(x << (y & 0x1f));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberShr) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
+ return *isolate->factory()->NewNumberFromUint(x >> (y & 0x1f));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_NumberSar) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
- return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
+ return *isolate->factory()->NewNumberFromInt(
+ ArithmeticShiftRight(x, y & 0x1f));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
+RUNTIME_FUNCTION(Runtime_NumberEquals) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
@@ -7446,31 +7573,32 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_StringEquals) {
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(String, x, 0);
- CONVERT_ARG_CHECKED(String, y, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
- bool not_equal = !x->Equals(y);
+ bool not_equal = !String::Equals(x, y);
// This is slightly convoluted because the value that signifies
// equality is 0 and inequality is 1 so we have to negate the result
// from String::Equals.
ASSERT(not_equal == 0 || not_equal == 1);
- STATIC_CHECK(EQUAL == 0);
- STATIC_CHECK(NOT_EQUAL == 1);
+ STATIC_ASSERT(EQUAL == 0);
+ STATIC_ASSERT(NOT_EQUAL == 1);
return Smi::FromInt(not_equal);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
+RUNTIME_FUNCTION(Runtime_NumberCompare) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 3);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- if (std::isnan(x) || std::isnan(y)) return args[2];
+ CONVERT_ARG_HANDLE_CHECKED(Object, uncomparable_result, 2)
+ if (std::isnan(x) || std::isnan(y)) return *uncomparable_result;
if (x == y) return Smi::FromInt(EQUAL);
if (isless(x, y)) return Smi::FromInt(LESS);
return Smi::FromInt(GREATER);
@@ -7479,7 +7607,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
// Compare two Smis as if they were converted to strings and then
// compared lexicographically.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
+RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(x_value, 0);
@@ -7554,27 +7682,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
}
-static Object* StringCharacterStreamCompare(RuntimeState* state,
- String* x,
- String* y) {
- StringCharacterStream stream_x(x, state->string_iterator_compare_x());
- StringCharacterStream stream_y(y, state->string_iterator_compare_y());
- while (stream_x.HasMore() && stream_y.HasMore()) {
- int d = stream_x.GetNext() - stream_y.GetNext();
- if (d < 0) return Smi::FromInt(LESS);
- else if (d > 0) return Smi::FromInt(GREATER);
+RUNTIME_FUNCTION(RuntimeHidden_StringCompare) {
+ HandleScope handle_scope(isolate);
+ ASSERT(args.length() == 2);
+
+ CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
+
+ isolate->counters()->string_compare_runtime()->Increment();
+
+ // A few fast case tests before we flatten.
+ if (x.is_identical_to(y)) return Smi::FromInt(EQUAL);
+ if (y->length() == 0) {
+ if (x->length() == 0) return Smi::FromInt(EQUAL);
+ return Smi::FromInt(GREATER);
+ } else if (x->length() == 0) {
+ return Smi::FromInt(LESS);
}
- // x is (non-trivial) prefix of y:
- if (stream_y.HasMore()) return Smi::FromInt(LESS);
- // y is prefix of x:
- return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
-}
+ int d = x->Get(0) - y->Get(0);
+ if (d < 0) return Smi::FromInt(LESS);
+ else if (d > 0) return Smi::FromInt(GREATER);
+ // Slow case.
+ x = String::Flatten(x);
+ y = String::Flatten(y);
-static Object* FlatStringCompare(String* x, String* y) {
- ASSERT(x->IsFlat());
- ASSERT(y->IsFlat());
+ DisallowHeapAllocation no_gc;
Object* equal_prefix_result = Smi::FromInt(EQUAL);
int prefix_length = x->length();
if (y->length() < prefix_length) {
@@ -7584,7 +7718,6 @@ static Object* FlatStringCompare(String* x, String* y) {
equal_prefix_result = Smi::FromInt(LESS);
}
int r;
- DisallowHeapAllocation no_gc;
String::FlatContent x_content = x->GetFlatContent();
String::FlatContent y_content = y->GetFlatContent();
if (x_content.IsAscii()) {
@@ -7612,82 +7745,60 @@ static Object* FlatStringCompare(String* x, String* y) {
} else {
result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
}
- ASSERT(result ==
- StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y));
return result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 2);
-
- CONVERT_ARG_CHECKED(String, x, 0);
- CONVERT_ARG_CHECKED(String, y, 1);
-
- isolate->counters()->string_compare_runtime()->Increment();
-
- // A few fast case tests before we flatten.
- if (x == y) return Smi::FromInt(EQUAL);
- if (y->length() == 0) {
- if (x->length() == 0) return Smi::FromInt(EQUAL);
- return Smi::FromInt(GREATER);
- } else if (x->length() == 0) {
- return Smi::FromInt(LESS);
- }
-
- int d = x->Get(0) - y->Get(0);
- if (d < 0) return Smi::FromInt(LESS);
- else if (d > 0) return Smi::FromInt(GREATER);
-
- Object* obj;
- { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
-
- return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
- : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
+#define RUNTIME_UNARY_MATH(Name, name) \
+RUNTIME_FUNCTION(Runtime_Math##Name) { \
+ HandleScope scope(isolate); \
+ ASSERT(args.length() == 1); \
+ isolate->counters()->math_##name()->Increment(); \
+ CONVERT_DOUBLE_ARG_CHECKED(x, 0); \
+ return *isolate->factory()->NewHeapNumber(std::name(x)); \
}
+RUNTIME_UNARY_MATH(Acos, acos)
+RUNTIME_UNARY_MATH(Asin, asin)
+RUNTIME_UNARY_MATH(Atan, atan)
+RUNTIME_UNARY_MATH(LogRT, log)
+#undef RUNTIME_UNARY_MATH
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
- isolate->counters()->math_acos()->Increment();
+RUNTIME_FUNCTION(Runtime_DoubleHi) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
+ uint64_t integer = double_to_uint64(x);
+ integer = (integer >> 32) & 0xFFFFFFFFu;
+ return *isolate->factory()->NewNumber(static_cast<int32_t>(integer));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DoubleLo) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
- isolate->counters()->math_asin()->Increment();
-
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
+ return *isolate->factory()->NewNumber(
+ static_cast<int32_t>(double_to_uint64(x) & 0xFFFFFFFFu));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
- isolate->counters()->math_atan()->Increment();
-
- CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
+RUNTIME_FUNCTION(Runtime_ConstructDouble) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
+ CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
+ uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
+ return *isolate->factory()->NewNumber(uint64_to_double(result));
}
static const double kPiDividedBy4 = 0.78539816339744830962;
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathAtan2) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
isolate->counters()->math_atan2()->Increment();
@@ -7703,57 +7814,37 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
if (y < 0) multiplier *= 3;
result = multiplier * kPiDividedBy4;
} else {
- result = atan2(x, y);
+ result = std::atan2(x, y);
}
- return isolate->heap()->AllocateHeapNumber(result);
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
- isolate->counters()->math_cos()->Increment();
-
- CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
+ return *isolate->factory()->NewNumber(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathExpRT) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_exp()->Increment();
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
lazily_initialize_fast_exp();
- return isolate->heap()->NumberFromDouble(fast_exp(x));
+ return *isolate->factory()->NewNumber(fast_exp(x));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathFloorRT) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_floor()->Increment();
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->heap()->NumberFromDouble(floor(x));
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
- isolate->counters()->math_log()->Increment();
-
- CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
+ return *isolate->factory()->NewNumber(std::floor(x));
}
// Slow version of Math.pow. We check for fast paths for special cases.
-// Used if SSE2/VFP3 is not available.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
- SealHandleScope shs(isolate);
+// Used if VFP3 is not available.
+RUNTIME_FUNCTION(RuntimeHidden_MathPowSlow) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
isolate->counters()->math_pow()->Increment();
@@ -7763,20 +7854,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
// custom powi() function than the generic pow().
if (args[1]->IsSmi()) {
int y = args.smi_at(1);
- return isolate->heap()->NumberFromDouble(power_double_int(x, y));
+ return *isolate->factory()->NewNumber(power_double_int(x, y));
}
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
double result = power_helper(x, y);
if (std::isnan(result)) return isolate->heap()->nan_value();
- return isolate->heap()->AllocateHeapNumber(result);
+ return *isolate->factory()->NewNumber(result);
}
// Fast version of Math.pow if we know that y is not an integer and y is not
// -0.5 or 0.5. Used as slow case from full codegen.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_MathPow) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
isolate->counters()->math_pow()->Increment();
@@ -7787,23 +7878,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
} else {
double result = power_double_double(x, y);
if (std::isnan(result)) return isolate->heap()->nan_value();
- return isolate->heap()->AllocateHeapNumber(result);
+ return *isolate->factory()->NewNumber(result);
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_RoundNumber) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(input, 0);
isolate->counters()->math_round()->Increment();
- if (!args[0]->IsHeapNumber()) {
- // Must be smi. Return the argument unchanged for all the other types
- // to make fuzz-natives test happy.
- return args[0];
+ if (!input->IsHeapNumber()) {
+ ASSERT(input->IsSmi());
+ return *input;
}
- HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
+ Handle<HeapNumber> number = Handle<HeapNumber>::cast(input);
double value = number->value();
int exponent = number->get_exponent();
@@ -7825,58 +7916,50 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
// If the magnitude is big enough, there's no place for fraction part. If we
// try to add 0.5 to this number, 1.0 will be added instead.
if (exponent >= 52) {
- return number;
+ return *number;
}
if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
// Do not call NumberFromDouble() to avoid extra checks.
- return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
+ return *isolate->factory()->NewNumber(std::floor(value + 0.5));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
- isolate->counters()->math_sin()->Increment();
-
- CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathSqrtRT) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_sqrt()->Increment();
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
+ return *isolate->factory()->NewNumber(fast_sqrt(x));
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MathFround) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
- isolate->counters()->math_tan()->Increment();
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
+ float xf = static_cast<float>(x);
+ return *isolate->factory()->NewNumber(xf);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
+RUNTIME_FUNCTION(Runtime_DateMakeDay) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(year, 0);
CONVERT_SMI_ARG_CHECKED(month, 1);
- return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
+ int days = isolate->date_cache()->DaysFromYearMonth(year, month);
+ RUNTIME_ASSERT(Smi::IsValid(days));
+ return Smi::FromInt(days);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
+RUNTIME_FUNCTION(Runtime_DateSetValue) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -7886,40 +7969,38 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
DateCache* date_cache = isolate->date_cache();
- Object* value = NULL;
+ Handle<Object> value;;
bool is_value_nan = false;
if (std::isnan(time)) {
- value = isolate->heap()->nan_value();
+ value = isolate->factory()->nan_value();
is_value_nan = true;
} else if (!is_utc &&
(time < -DateCache::kMaxTimeBeforeUTCInMs ||
time > DateCache::kMaxTimeBeforeUTCInMs)) {
- value = isolate->heap()->nan_value();
+ value = isolate->factory()->nan_value();
is_value_nan = true;
} else {
time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
if (time < -DateCache::kMaxTimeInMs ||
time > DateCache::kMaxTimeInMs) {
- value = isolate->heap()->nan_value();
+ value = isolate->factory()->nan_value();
is_value_nan = true;
} else {
- MaybeObject* maybe_result =
- isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
- if (!maybe_result->ToObject(&value)) return maybe_result;
+ value = isolate->factory()->NewNumber(DoubleToInteger(time));
}
}
- date->SetValue(value, is_value_nan);
- return value;
+ date->SetValue(*value, is_value_nan);
+ return *value;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
+RUNTIME_FUNCTION(RuntimeHidden_NewSloppyArguments) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- Handle<JSFunction> callee = args.at<JSFunction>(0);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
Object** parameters = reinterpret_cast<Object**>(args[1]);
- const int argument_count = Smi::cast(args[2])->value();
+ CONVERT_SMI_ARG_CHECKED(argument_count, 2);
Handle<JSObject> result =
isolate->factory()->NewArgumentsObject(callee, argument_count);
@@ -7931,13 +8012,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
Handle<FixedArray> parameter_map =
isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
parameter_map->set_map(
- isolate->heap()->non_strict_arguments_elements_map());
+ isolate->heap()->sloppy_arguments_elements_map());
- Handle<Map> old_map(result->map());
- Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
- new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
+ Handle<Map> map = Map::Copy(handle(result->map()));
+ map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
- result->set_map(*new_map);
+ result->set_map(*map);
result->set_elements(*parameter_map);
// Store the context and the arguments array at the beginning of the
@@ -8008,54 +8088,42 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_NewStrictArguments) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
-
- JSFunction* callee = JSFunction::cast(args[0]);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
Object** parameters = reinterpret_cast<Object**>(args[1]);
- const int length = args.smi_at(2);
+ CONVERT_SMI_ARG_CHECKED(length, 2);
- Object* result;
- { MaybeObject* maybe_result =
- isolate->heap()->AllocateArgumentsObject(callee, length);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- // Allocate the elements if needed.
- if (length > 0) {
- // Allocate the fixed array.
- FixedArray* array;
- { MaybeObject* maybe_obj =
- isolate->heap()->AllocateUninitializedFixedArray(length);
- if (!maybe_obj->To(&array)) return maybe_obj;
- }
+ Handle<JSObject> result =
+ isolate->factory()->NewArgumentsObject(callee, length);
+ if (length > 0) {
+ Handle<FixedArray> array =
+ isolate->factory()->NewUninitializedFixedArray(length);
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) {
array->set(i, *--parameters, mode);
}
- JSObject::cast(result)->set_elements(array);
+ result->set_elements(*array);
}
- return result;
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosureFromStubFailure) {
+RUNTIME_FUNCTION(RuntimeHidden_NewClosureFromStubFailure) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
Handle<Context> context(isolate->context());
PretenureFlag pretenure_flag = NOT_TENURED;
- Handle<JSFunction> result =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
- context,
- pretenure_flag);
- return *result;
+ return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
+ shared, context, pretenure_flag);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
+RUNTIME_FUNCTION(RuntimeHidden_NewClosure) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
@@ -8065,11 +8133,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
// The caller ensures that we pretenure closures that are assigned
// directly to properties.
PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
- Handle<JSFunction> result =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
- context,
- pretenure_flag);
- return *result;
+ return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
+ shared, context, pretenure_flag);
}
@@ -8088,23 +8153,22 @@ static SmartArrayPointer<Handle<Object> > GetCallerArguments(
if (functions.length() > 1) {
int inlined_jsframe_index = functions.length() - 1;
JSFunction* inlined_function = functions[inlined_jsframe_index];
- Vector<SlotRef> args_slots =
- SlotRef::ComputeSlotMappingForArguments(
- frame,
- inlined_jsframe_index,
- inlined_function->shared()->formal_parameter_count());
+ SlotRefValueBuilder slot_refs(
+ frame,
+ inlined_jsframe_index,
+ inlined_function->shared()->formal_parameter_count());
- int args_count = args_slots.length();
+ int args_count = slot_refs.args_length();
*total_argc = prefix_argc + args_count;
SmartArrayPointer<Handle<Object> > param_data(
NewArray<Handle<Object> >(*total_argc));
+ slot_refs.Prepare(isolate);
for (int i = 0; i < args_count; i++) {
- Handle<Object> val = args_slots[i].GetValue(isolate);
+ Handle<Object> val = slot_refs.GetNext(isolate, 0);
param_data[prefix_argc + i] = val;
}
-
- args_slots.Dispose();
+ slot_refs.Finish(isolate);
return param_data;
} else {
@@ -8124,12 +8188,13 @@ static SmartArrayPointer<Handle<Object> > GetCallerArguments(
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
+RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
- RUNTIME_ASSERT(args[3]->IsNumber());
- Handle<Object> bindee = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, bindee, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2);
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
// TODO(lrn): Create bound function in C++ code from premade shared info.
bound_function->shared()->set_bound(true);
@@ -8139,10 +8204,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
GetCallerArguments(isolate, 0, &argc);
// Don't count the this-arg.
if (argc > 0) {
- ASSERT(*arguments[0] == args[2]);
+ RUNTIME_ASSERT(arguments[0].is_identical_to(this_object));
argc--;
} else {
- ASSERT(args[2]->IsUndefined());
+ RUNTIME_ASSERT(this_object->IsUndefined());
}
// Initialize array of bindings (function, this, and any existing arguments
// if the function was already bound).
@@ -8151,6 +8216,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
Handle<FixedArray> old_bindings(
JSFunction::cast(*bindee)->function_bindings());
+ RUNTIME_ASSERT(old_bindings->length() > JSFunction::kBoundFunctionIndex);
new_bindings =
isolate->factory()->NewFixedArray(old_bindings->length() + argc);
bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
@@ -8163,7 +8229,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
new_bindings = isolate->factory()->NewFixedArray(array_size);
new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
- new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
+ new_bindings->set(JSFunction::kBoundThisIndex, *this_object);
i = 2;
}
// Copy arguments, skipping the first which is "this_arg".
@@ -8174,17 +8240,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
isolate->heap()->fixed_cow_array_map());
bound_function->set_function_bindings(*new_bindings);
- // Update length.
+ // Update length. Have to remove the prototype first so that map migration
+ // is happy about the number of fields.
+ RUNTIME_ASSERT(bound_function->RemovePrototype());
+ Handle<Map> bound_function_map(
+ isolate->native_context()->bound_function_map());
+ JSObject::MigrateToMap(bound_function, bound_function_map);
Handle<String> length_string = isolate->factory()->length_string();
- Handle<Object> new_length(args.at<Object>(3));
PropertyAttributes attr =
static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
- ForceSetProperty(bound_function, length_string, new_length, attr);
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(bound_function, length_string,
+ new_length, attr));
return *bound_function;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
+RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) {
HandleScope handles(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
@@ -8192,7 +8265,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
if (function->shared()->bound()) {
Handle<FixedArray> bindings(function->function_bindings());
- ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
+ RUNTIME_ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
return *isolate->factory()->NewJSArrayWithElements(bindings);
}
}
@@ -8200,7 +8273,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
+RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
// First argument is a function to use as a constructor.
@@ -8227,32 +8300,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
}
if (!bound_function->IsJSFunction()) {
- bool exception_thrown;
- bound_function = Execution::TryGetConstructorDelegate(isolate,
- bound_function,
- &exception_thrown);
- if (exception_thrown) return Failure::Exception();
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, bound_function,
+ Execution::TryGetConstructorDelegate(isolate, bound_function));
}
ASSERT(bound_function->IsJSFunction());
- bool exception = false;
- Handle<Object> result =
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
Execution::New(Handle<JSFunction>::cast(bound_function),
- total_argc, *param_data, &exception);
- if (exception) {
- return Failure::Exception();
- }
- ASSERT(!result.is_null());
+ total_argc, param_data.get()));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
-
- Handle<Object> constructor = args.at<Object>(0);
-
+static Object* Runtime_NewObjectHelper(Isolate* isolate,
+ Handle<Object> constructor,
+ Handle<AllocationSite> site) {
// If the constructor isn't a proper function we throw a type error.
if (!constructor->IsJSFunction()) {
Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
@@ -8272,13 +8337,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
return isolate->Throw(*type_error);
}
-#ifdef ENABLE_DEBUGGER_SUPPORT
Debug* debug = isolate->debug();
// Handle stepping into constructors if step into is active.
if (debug->StepInActive()) {
debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
}
-#endif
if (function->has_initial_map()) {
if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
@@ -8299,20 +8362,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
// The function should be compiled for the optimization hints to be
// available.
- JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION);
+ Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
- Handle<SharedFunctionInfo> shared(function->shared(), isolate);
- if (!function->has_initial_map() &&
- shared->IsInobjectSlackTrackingInProgress()) {
- // The tracking is already in progress for another function. We can only
- // track one initial_map at a time, so we force the completion before the
- // function is called as a constructor for the first time.
- shared->CompleteInobjectSlackTracking();
+ Handle<JSObject> result;
+ if (site.is_null()) {
+ result = isolate->factory()->NewJSObject(function);
+ } else {
+ result = isolate->factory()->NewJSObjectWithMemento(function, site);
}
- Handle<JSObject> result = isolate->factory()->NewJSObject(function);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
-
isolate->counters()->constructed_objects()->Increment();
isolate->counters()->constructed_objects_runtime()->Increment();
@@ -8320,53 +8378,88 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
+RUNTIME_FUNCTION(RuntimeHidden_NewObject) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
+ return Runtime_NewObjectHelper(isolate,
+ constructor,
+ Handle<AllocationSite>::null());
+}
+
+
+RUNTIME_FUNCTION(RuntimeHidden_NewObjectWithAllocationSite) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, feedback, 0);
+ Handle<AllocationSite> site;
+ if (feedback->IsAllocationSite()) {
+ // The feedback can be an AllocationSite or undefined.
+ site = Handle<AllocationSite>::cast(feedback);
+ }
+ return Runtime_NewObjectHelper(isolate, constructor, site);
+}
+
+
+RUNTIME_FUNCTION(RuntimeHidden_FinalizeInstanceSize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
- function->shared()->CompleteInobjectSlackTracking();
+ function->CompleteInobjectSlackTracking();
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
+RUNTIME_FUNCTION(RuntimeHidden_CompileUnoptimized) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
-
- Handle<JSFunction> function = args.at<JSFunction>(0);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
#ifdef DEBUG
if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
- PrintF("[lazy: ");
+ PrintF("[unoptimized: ");
function->PrintName();
PrintF("]\n");
}
#endif
// Compile the target function.
- ASSERT(!function->is_compiled());
- if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
- return Failure::Exception();
- }
+ ASSERT(function->shared()->allows_lazy_compilation());
+
+ Handle<Code> code;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, code,
+ Compiler::GetUnoptimizedCode(function));
+ function->ReplaceCode(*code);
// All done. Return the compiled code.
ASSERT(function->is_compiled());
- return function->code();
+ ASSERT(function->code()->kind() == Code::FUNCTION ||
+ (FLAG_always_opt &&
+ function->code()->kind() == Code::OPTIMIZED_FUNCTION));
+ return *code;
}
-bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
- // If the function is not compiled ignore the lazy
- // recompilation. This can happen if the debugger is activated and
- // the function is returned to the not compiled state.
- if (!function->shared()->is_compiled()) return false;
-
- // If the function is not optimizable or debugger is active continue using the
- // code from the full compiler.
- if (!isolate->use_crankshaft() ||
- function->shared()->optimization_disabled() ||
- isolate->DebuggerHasBreakPoints()) {
+RUNTIME_FUNCTION(RuntimeHidden_CompileOptimized) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+ CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1);
+
+ Handle<Code> unoptimized(function->shared()->code());
+ if (!function->shared()->is_compiled()) {
+ // If the function is not compiled, do not optimize.
+ // This can happen if the debugger is activated and
+ // the function is returned to the not compiled state.
+ // TODO(yangguo): reconsider this.
+ function->ReplaceCode(function->shared()->code());
+ } else if (!isolate->use_crankshaft() ||
+ function->shared()->optimization_disabled() ||
+ isolate->DebuggerHasBreakPoints()) {
+ // If the function is not optimizable or debugger is active continue
+ // using the code from the full compiler.
if (FLAG_trace_opt) {
PrintF("[failed to optimize ");
function->PrintName();
@@ -8374,52 +8467,26 @@ bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
function->shared()->optimization_disabled() ? "F" : "T",
isolate->DebuggerHasBreakPoints() ? "T" : "F");
}
- return false;
+ function->ReplaceCode(*unoptimized);
+ } else {
+ Compiler::ConcurrencyMode mode = concurrent ? Compiler::CONCURRENT
+ : Compiler::NOT_CONCURRENT;
+ Handle<Code> code;
+ if (Compiler::GetOptimizedCode(
+ function, unoptimized, mode).ToHandle(&code)) {
+ function->ReplaceCode(*code);
+ } else {
+ function->ReplaceCode(*unoptimized);
+ }
}
- return true;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- Handle<JSFunction> function = args.at<JSFunction>(0);
- if (!AllowOptimization(isolate, function)) {
- function->ReplaceCode(function->shared()->code());
- return function->code();
- }
- function->shared()->code()->set_profiler_ticks(0);
- if (JSFunction::CompileOptimized(function, CLEAR_EXCEPTION)) {
- return function->code();
- }
- if (FLAG_trace_opt) {
- PrintF("[failed to optimize ");
- function->PrintName();
- PrintF(": optimized compilation failed]\n");
- }
- function->ReplaceCode(function->shared()->code());
+ ASSERT(function->code()->kind() == Code::FUNCTION ||
+ function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
+ function->IsInOptimizationQueue());
return function->code();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ConcurrentRecompile) {
- HandleScope handle_scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
- if (!AllowOptimization(isolate, function)) {
- function->ReplaceCode(function->shared()->code());
- return isolate->heap()->undefined_value();
- }
- function->shared()->code()->set_profiler_ticks(0);
- ASSERT(isolate->concurrent_recompilation_enabled());
- if (!Compiler::RecompileConcurrent(function)) {
- function->ReplaceCode(function->shared()->code());
- }
- return isolate->heap()->undefined_value();
-}
-
-
class ActivationsFinder : public ThreadVisitor {
public:
Code* code_;
@@ -8443,7 +8510,7 @@ class ActivationsFinder : public ThreadVisitor {
};
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyStubFailure) {
+RUNTIME_FUNCTION(RuntimeHidden_NotifyStubFailure) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
@@ -8453,12 +8520,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyStubFailure) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
+RUNTIME_FUNCTION(RuntimeHidden_NotifyDeoptimized) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- RUNTIME_ASSERT(args[0]->IsSmi());
+ CONVERT_SMI_ARG_CHECKED(type_arg, 0);
Deoptimizer::BailoutType type =
- static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
+ static_cast<Deoptimizer::BailoutType>(type_arg);
Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
ASSERT(AllowHeapAllocation::IsAllowed());
@@ -8496,6 +8563,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
PrintF("]\n");
}
function->ReplaceCode(function->shared()->code());
+ // Evict optimized code for this function from the cache so that it
+ // doesn't get used for new closures.
+ function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
+ "notify deoptimized");
}
} else {
// TODO(titzer): we should probably do DeoptimizeCodeList(code)
@@ -8503,16 +8574,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
// If there is an index by shared function info, all the better.
Deoptimizer::DeoptimizeFunction(*function);
}
- // Evict optimized code for this function from the cache so that it doesn't
- // get used for new closures.
- function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
- "notify deoptimized");
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
+RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -8524,21 +8591,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
+RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+ function->shared()->ClearTypeFeedbackInfo();
Code* unoptimized = function->shared()->code();
if (unoptimized->kind() == Code::FUNCTION) {
unoptimized->ClearInlineCaches();
- unoptimized->ClearTypeFeedbackCells(isolate->heap());
}
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
+RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 0);
#if defined(USE_SIMULATOR)
return isolate->heap()->true_value();
#else
@@ -8547,20 +8615,26 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConcurrentRecompilationSupported) {
- HandleScope scope(isolate);
- return isolate->concurrent_recompilation_enabled()
- ? isolate->heap()->true_value() : isolate->heap()->false_value();
+RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
+ SealHandleScope shs(isolate);
+ ASSERT(args.length() == 0);
+ return isolate->heap()->ToBoolean(
+ isolate->concurrent_recompilation_enabled());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
+RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
- if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
- function->MarkForLazyRecompilation();
+ if (!function->IsOptimizable() &&
+ !function->IsMarkedForConcurrentOptimization() &&
+ !function->IsInOptimizationQueue()) {
+ return isolate->heap()->undefined_value();
+ }
+
+ function->MarkForOptimization();
Code* unoptimized = function->shared()->code();
if (args.length() == 2 &&
@@ -8570,12 +8644,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
// Start patching from the currently patched loop nesting level.
int current_level = unoptimized->allow_osr_at_loop_nesting_level();
ASSERT(BackEdgeTable::Verify(isolate, unoptimized, current_level));
- for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
- unoptimized->set_allow_osr_at_loop_nesting_level(i);
- isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
+ if (FLAG_use_osr) {
+ for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
+ unoptimized->set_allow_osr_at_loop_nesting_level(i);
+ isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
+ }
}
- } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent"))) {
- function->MarkForConcurrentRecompilation();
+ } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent")) &&
+ isolate->concurrent_recompilation_enabled()) {
+ function->MarkForConcurrentOptimization();
}
}
@@ -8583,17 +8660,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) {
+RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, function, 0);
- ASSERT(!function->IsOptimized());
function->shared()->set_optimization_disabled(true);
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
+RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
if (!isolate->use_crankshaft()) {
@@ -8609,7 +8685,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
if (isolate->concurrent_recompilation_enabled() &&
sync_with_compiler_thread) {
- while (function->IsInRecompileQueue()) {
+ while (function->IsInOptimizationQueue()) {
isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
OS::Sleep(50);
}
@@ -8628,14 +8704,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_UnblockConcurrentRecompilation) {
+RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
+ ASSERT(args.length() == 0);
RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
+ RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
isolate->optimizing_compiler_thread()->Unblock();
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
+RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -8645,9 +8723,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
static bool IsSuitableForOnStackReplacement(Isolate* isolate,
Handle<JSFunction> function,
- Handle<Code> unoptimized) {
+ Handle<Code> current_code) {
// Keep track of whether we've succeeded in optimizing.
- if (!isolate->use_crankshaft() || !unoptimized->optimizable()) return false;
+ if (!isolate->use_crankshaft() || !current_code->optimizable()) return false;
// If we are trying to do OSR when there are already optimized
// activations of the function, it means (a) the function is directly or
// indirectly recursive and (b) an optimized invocation has been
@@ -8662,76 +8740,88 @@ static bool IsSuitableForOnStackReplacement(Isolate* isolate,
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
+RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
HandleScope scope(isolate);
- ASSERT(args.length() == 2);
+ ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
- CONVERT_NUMBER_CHECKED(uint32_t, pc_offset, Uint32, args[1]);
- Handle<Code> unoptimized(function->shared()->code(), isolate);
+ Handle<Code> caller_code(function->shared()->code());
-#ifdef DEBUG
+ // We're not prepared to handle a function with arguments object.
+ ASSERT(!function->shared()->uses_arguments());
+
+ RUNTIME_ASSERT(FLAG_use_osr);
+
+ // Passing the PC in the javascript frame from the caller directly is
+ // not GC safe, so we walk the stack to get it.
JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = it.frame();
- ASSERT_EQ(frame->function(), *function);
- ASSERT_EQ(frame->LookupCode(), *unoptimized);
- ASSERT(unoptimized->contains(frame->pc()));
+ if (!caller_code->contains(frame->pc())) {
+ // Code on the stack may not be the code object referenced by the shared
+ // function info. It may have been replaced to include deoptimization data.
+ caller_code = Handle<Code>(frame->LookupCode());
+ }
+
+ uint32_t pc_offset = static_cast<uint32_t>(
+ frame->pc() - caller_code->instruction_start());
- ASSERT(pc_offset ==
- static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start()));
+#ifdef DEBUG
+ ASSERT_EQ(frame->function(), *function);
+ ASSERT_EQ(frame->LookupCode(), *caller_code);
+ ASSERT(caller_code->contains(frame->pc()));
#endif // DEBUG
- // We're not prepared to handle a function with arguments object.
- ASSERT(!function->shared()->uses_arguments());
+ BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset);
+ ASSERT(!ast_id.IsNone());
+
+ Compiler::ConcurrencyMode mode =
+ isolate->concurrent_osr_enabled() &&
+ (function->shared()->ast_node_count() > 512) ? Compiler::CONCURRENT
+ : Compiler::NOT_CONCURRENT;
Handle<Code> result = Handle<Code>::null();
- BailoutId ast_id = BailoutId::None();
- if (isolate->concurrent_osr_enabled()) {
- if (isolate->optimizing_compiler_thread()->
- IsQueuedForOSR(function, pc_offset)) {
- // Still waiting for the optimizing compiler thread to finish. Carry on.
+ OptimizedCompileJob* job = NULL;
+ if (mode == Compiler::CONCURRENT) {
+ // Gate the OSR entry with a stack check.
+ BackEdgeTable::AddStackCheck(caller_code, pc_offset);
+ // Poll already queued compilation jobs.
+ OptimizingCompilerThread* thread = isolate->optimizing_compiler_thread();
+ if (thread->IsQueuedForOSR(function, ast_id)) {
if (FLAG_trace_osr) {
- PrintF("[COSR - polling recompile tasks for ");
+ PrintF("[OSR - Still waiting for queued: ");
function->PrintName();
- PrintF("]\n");
+ PrintF(" at AST id %d]\n", ast_id.ToInt());
}
return NULL;
}
- RecompileJob* job = isolate->optimizing_compiler_thread()->
- FindReadyOSRCandidate(function, pc_offset);
+ job = thread->FindReadyOSRCandidate(function, ast_id);
+ }
- if (job == NULL) {
- if (IsSuitableForOnStackReplacement(isolate, function, unoptimized) &&
- Compiler::RecompileConcurrent(function, pc_offset)) {
- if (function->IsMarkedForLazyRecompilation() ||
- function->IsMarkedForConcurrentRecompilation()) {
- // Prevent regular recompilation if we queue this for OSR.
- // TODO(yangguo): remove this as soon as OSR becomes one-shot.
- function->ReplaceCode(*unoptimized);
- }
- return NULL;
- }
- // Fall through to the end in case of failure.
- } else {
- // TODO(titzer): don't install the OSR code into the function.
- ast_id = job->info()->osr_ast_id();
- result = Compiler::InstallOptimizedCode(job);
+ if (job != NULL) {
+ if (FLAG_trace_osr) {
+ PrintF("[OSR - Found ready: ");
+ function->PrintName();
+ PrintF(" at AST id %d]\n", ast_id.ToInt());
}
- } else if (IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
- ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset);
- ASSERT(!ast_id.IsNone());
+ result = Compiler::GetConcurrentlyOptimizedCode(job);
+ } else if (IsSuitableForOnStackReplacement(isolate, function, caller_code)) {
if (FLAG_trace_osr) {
- PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt());
+ PrintF("[OSR - Compiling: ");
function->PrintName();
- PrintF("]\n");
+ PrintF(" at AST id %d]\n", ast_id.ToInt());
+ }
+ MaybeHandle<Code> maybe_result = Compiler::GetOptimizedCode(
+ function, caller_code, mode, ast_id);
+ if (maybe_result.ToHandle(&result) &&
+ result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
+ // Optimization is queued. Return to check later.
+ return NULL;
}
- // Attempt OSR compilation.
- result = JSFunction::CompileOsr(function, ast_id, CLEAR_EXCEPTION);
}
// Revert the patched back edge table, regardless of whether OSR succeeds.
- BackEdgeTable::Revert(isolate, *unoptimized);
+ BackEdgeTable::Revert(isolate, *caller_code);
// Check whether we ended up with usable optimized code.
if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
@@ -8741,58 +8831,72 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
if (data->OsrPcOffset()->value() >= 0) {
ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
if (FLAG_trace_osr) {
- PrintF("[OSR - entry at AST id %d, offset %d in optimized code]\n",
+ PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
ast_id.ToInt(), data->OsrPcOffset()->value());
}
// TODO(titzer): this is a massive hack to make the deopt counts
// match. Fix heuristics for reenabling optimizations!
function->shared()->increment_deopt_count();
+
+ // TODO(titzer): Do not install code into the function.
+ function->ReplaceCode(*result);
return *result;
}
}
+ // Failed.
if (FLAG_trace_osr) {
- PrintF("[OSR - optimization failed for ");
+ PrintF("[OSR - Failed: ");
function->PrintName();
- PrintF("]\n");
+ PrintF(" at AST id %d]\n", ast_id.ToInt());
}
- if (function->IsMarkedForLazyRecompilation() ||
- function->IsMarkedForConcurrentRecompilation()) {
+ if (!function->IsOptimized()) {
function->ReplaceCode(function->shared()->code());
}
return NULL;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) {
+RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
SealHandleScope shs(isolate);
- ASSERT(args.length() == 2);
+ ASSERT(args.length() == 2 || args.length() == 3);
#ifdef DEBUG
CONVERT_SMI_ARG_CHECKED(interval, 0);
CONVERT_SMI_ARG_CHECKED(timeout, 1);
isolate->heap()->set_allocation_timeout(timeout);
FLAG_gc_interval = interval;
+ if (args.length() == 3) {
+ // Enable/disable inline allocation if requested.
+ CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
+ if (inline_allocation) {
+ isolate->heap()->EnableInlineAllocation();
+ } else {
+ isolate->heap()->DisableInlineAllocation();
+ }
+ }
#endif
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
+RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 0);
RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
+RUNTIME_FUNCTION(Runtime_GetRootNaN) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 0);
RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
return isolate->heap()->nan_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
+RUNTIME_FUNCTION(Runtime_Call) {
HandleScope scope(isolate);
ASSERT(args.length() >= 2);
int argc = args.length() - 2;
@@ -8811,33 +8915,32 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
}
for (int i = 0; i < argc; ++i) {
- MaybeObject* maybe = args[1 + i];
- Object* object;
- if (!maybe->To<Object>(&object)) return maybe;
- argv[i] = Handle<Object>(object, isolate);
+ argv[i] = Handle<Object>(args[1 + i], isolate);
}
- bool threw;
Handle<JSReceiver> hfun(fun);
Handle<Object> hreceiver(receiver, isolate);
- Handle<Object> result = Execution::Call(
- isolate, hfun, hreceiver, argc, argv, &threw, true);
-
- if (threw) return Failure::Exception();
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Execution::Call(isolate, hfun, hreceiver, argc, argv, true));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
+RUNTIME_FUNCTION(Runtime_Apply) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
- Handle<Object> receiver = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
CONVERT_SMI_ARG_CHECKED(offset, 3);
CONVERT_SMI_ARG_CHECKED(argc, 4);
RUNTIME_ASSERT(offset >= 0);
- RUNTIME_ASSERT(argc >= 0);
+ // Loose upper bound to allow fuzzing. We'll most likely run out of
+ // stack space before hitting this limit.
+ static int kMaxArgc = 1000000;
+ RUNTIME_ASSERT(argc >= 0 && argc <= kMaxArgc);
// If there are too many arguments, allocate argv via malloc.
const int argv_small_size = 10;
@@ -8851,174 +8954,152 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
}
for (int i = 0; i < argc; ++i) {
- argv[i] = Object::GetElement(isolate, arguments, offset + i);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, argv[i],
+ Object::GetElement(isolate, arguments, offset + i));
}
- bool threw;
- Handle<Object> result = Execution::Call(
- isolate, fun, receiver, argc, argv, &threw, true);
-
- if (threw) return Failure::Exception();
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Execution::Call(isolate, fun, receiver, argc, argv, true));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
+RUNTIME_FUNCTION(Runtime_GetFunctionDelegate) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- RUNTIME_ASSERT(!args[0]->IsJSFunction());
- return *Execution::GetFunctionDelegate(isolate, args.at<Object>(0));
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ RUNTIME_ASSERT(!object->IsJSFunction());
+ return *Execution::GetFunctionDelegate(isolate, object);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
+RUNTIME_FUNCTION(Runtime_GetConstructorDelegate) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- RUNTIME_ASSERT(!args[0]->IsJSFunction());
- return *Execution::GetConstructorDelegate(isolate, args.at<Object>(0));
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ RUNTIME_ASSERT(!object->IsJSFunction());
+ return *Execution::GetConstructorDelegate(isolate, object);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewGlobalContext) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_NewGlobalContext) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(JSFunction, function, 0);
- CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
- Context* result;
- MaybeObject* maybe_result =
- isolate->heap()->AllocateGlobalContext(function, scope_info);
- if (!maybe_result->To(&result)) return maybe_result;
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+ CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
+ Handle<Context> result =
+ isolate->factory()->NewGlobalContext(function, scope_info);
ASSERT(function->context() == isolate->context());
ASSERT(function->context()->global_object() == result->global_object());
- isolate->set_context(result);
- result->global_object()->set_global_context(result);
-
- return result; // non-failure
+ result->global_object()->set_global_context(*result);
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_NewFunctionContext) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(JSFunction, function, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
int length = function->shared()->scope_info()->ContextLength();
- Context* result;
- MaybeObject* maybe_result =
- isolate->heap()->AllocateFunctionContext(length, function);
- if (!maybe_result->To(&result)) return maybe_result;
-
- isolate->set_context(result);
-
- return result; // non-failure
+ return *isolate->factory()->NewFunctionContext(length, function);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_PushWithContext) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- JSReceiver* extension_object;
+ Handle<JSReceiver> extension_object;
if (args[0]->IsJSReceiver()) {
- extension_object = JSReceiver::cast(args[0]);
+ extension_object = args.at<JSReceiver>(0);
} else {
- // Convert the object to a proper JavaScript object.
- MaybeObject* maybe_js_object = args[0]->ToObject(isolate);
- if (!maybe_js_object->To(&extension_object)) {
- if (Failure::cast(maybe_js_object)->IsInternalError()) {
- HandleScope scope(isolate);
- Handle<Object> handle = args.at<Object>(0);
- Handle<Object> result =
- isolate->factory()->NewTypeError("with_expression",
- HandleVector(&handle, 1));
- return isolate->Throw(*result);
- } else {
- return maybe_js_object;
- }
+ // 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);
+ Handle<Object> result =
+ isolate->factory()->NewTypeError("with_expression",
+ HandleVector(&handle, 1));
+ return isolate->Throw(*result);
}
}
- JSFunction* function;
+ 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 = isolate->context()->native_context()->closure();
+ function = handle(isolate->context()->native_context()->closure());
} else {
- function = JSFunction::cast(args[1]);
+ function = args.at<JSFunction>(1);
}
- Context* context;
- MaybeObject* maybe_context =
- isolate->heap()->AllocateWithContext(function,
- isolate->context(),
- extension_object);
- if (!maybe_context->To(&context)) return maybe_context;
- isolate->set_context(context);
- return context;
+ Handle<Context> current(isolate->context());
+ Handle<Context> context = isolate->factory()->NewWithContext(
+ function, current, extension_object);
+ isolate->set_context(*context);
+ return *context;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_PushCatchContext) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
- String* name = String::cast(args[0]);
- Object* thrown_object = args[1];
- JSFunction* function;
+ 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 = isolate->context()->native_context()->closure();
+ function = handle(isolate->context()->native_context()->closure());
} else {
- function = JSFunction::cast(args[2]);
+ function = args.at<JSFunction>(2);
}
- Context* context;
- MaybeObject* maybe_context =
- isolate->heap()->AllocateCatchContext(function,
- isolate->context(),
- name,
- thrown_object);
- if (!maybe_context->To(&context)) return maybe_context;
- isolate->set_context(context);
- return context;
+ Handle<Context> current(isolate->context());
+ Handle<Context> context = isolate->factory()->NewCatchContext(
+ function, current, name, thrown_object);
+ isolate->set_context(*context);
+ return *context;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_PushBlockContext) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
- JSFunction* function;
+ 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 = isolate->context()->native_context()->closure();
+ function = handle(isolate->context()->native_context()->closure());
} else {
- function = JSFunction::cast(args[1]);
+ function = args.at<JSFunction>(1);
}
- Context* context;
- MaybeObject* maybe_context =
- isolate->heap()->AllocateBlockContext(function,
- isolate->context(),
- scope_info);
- if (!maybe_context->To(&context)) return maybe_context;
- isolate->set_context(context);
- return context;
+ Handle<Context> current(isolate->context());
+ Handle<Context> context = isolate->factory()->NewBlockContext(
+ function, current, scope_info);
+ isolate->set_context(*context);
+ return *context;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
+RUNTIME_FUNCTION(Runtime_IsJSModule) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* obj = args[0];
+ CONVERT_ARG_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSModule());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
+RUNTIME_FUNCTION(RuntimeHidden_PushModuleContext) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(index, 0);
@@ -9053,7 +9134,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) {
+RUNTIME_FUNCTION(RuntimeHidden_DeclareModules) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
@@ -9073,20 +9154,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) {
case VAR:
case LET:
case CONST:
- case CONST_HARMONY: {
+ case CONST_LEGACY: {
PropertyAttributes attr =
IsImmutableVariableMode(mode) ? FROZEN : SEALED;
Handle<AccessorInfo> info =
Accessors::MakeModuleExport(name, index, attr);
- Handle<Object> result = JSObject::SetAccessor(module, info);
- ASSERT(!(result.is_null() || result->IsUndefined()));
+ Handle<Object> result =
+ JSObject::SetAccessor(module, info).ToHandleChecked();
+ ASSERT(!result->IsUndefined());
USE(result);
break;
}
case MODULE: {
Object* referenced_context = Context::cast(host_context)->get(index);
Handle<JSModule> value(Context::cast(referenced_context)->module());
- JSReceiver::SetProperty(module, name, value, FROZEN, kStrictMode);
+ JSReceiver::SetProperty(module, name, value, FROZEN, STRICT).Assert();
break;
}
case INTERNAL:
@@ -9098,7 +9180,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) {
}
}
- JSObject::PreventExtensions(module);
+ JSObject::PreventExtensions(module).Assert();
}
ASSERT(!isolate->has_pending_exception());
@@ -9106,7 +9188,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
+RUNTIME_FUNCTION(RuntimeHidden_DeleteContextSlot) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -9137,8 +9219,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
// 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 = JSReceiver::DeleteProperty(object, name);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSReceiver::DeleteProperty(object, name));
return *result;
}
@@ -9153,12 +9237,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
// allocated by the caller, and passed as a pointer in a hidden first parameter.
#ifdef V8_HOST_ARCH_64_BIT
struct ObjectPair {
- MaybeObject* x;
- MaybeObject* y;
+ Object* x;
+ Object* y;
};
-static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
+static inline ObjectPair MakePair(Object* x, Object* y) {
ObjectPair result = {x, y};
// Pointers x and y returned in rax and rdx, in AMD-x64-abi.
// In Win64 they are assigned to a hidden first argument.
@@ -9166,20 +9250,18 @@ static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
}
#else
typedef uint64_t ObjectPair;
-static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
+static inline ObjectPair MakePair(Object* x, Object* y) {
+#if defined(V8_TARGET_LITTLE_ENDIAN)
return reinterpret_cast<uint32_t>(x) |
(reinterpret_cast<ObjectPair>(y) << 32);
-}
+#elif defined(V8_TARGET_BIG_ENDIAN)
+ return reinterpret_cast<uint32_t>(y) |
+ (reinterpret_cast<ObjectPair>(x) << 32);
+#else
+#error Unknown endianness
#endif
-
-
-static inline MaybeObject* Unhole(Heap* heap,
- MaybeObject* x,
- PropertyAttributes attributes) {
- ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
- USE(attributes);
- return x->IsTheHole() ? heap->undefined_value() : x;
}
+#endif
static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
@@ -9197,9 +9279,8 @@ static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
if (constructor != context_extension_function) 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. Implicit global
- // receivers are indicated with the hole value.
- return isolate->heap()->the_hole_value();
+ // context extension object - introduced via eval.
+ return isolate->heap()->undefined_value();
}
@@ -9225,7 +9306,7 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
&attributes,
&binding_flags);
if (isolate->has_pending_exception()) {
- return MakePair(Failure::Exception(), NULL);
+ return MakePair(isolate->heap()->exception(), NULL);
}
// If the index is non-negative, the slot has been found in a context.
@@ -9233,11 +9314,7 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
ASSERT(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.
- //
- // Use the hole as the receiver to signal that the receiver is implicit
- // and that the global receiver should be used (as distinguished from an
- // explicit receiver that happens to be a global object).
- Handle<Object> receiver = isolate->factory()->the_hole_value();
+ Handle<Object> receiver = isolate->factory()->undefined_value();
Object* value = Context::cast(*holder)->get(index);
// Check for uninitialized bindings.
switch (binding_flags) {
@@ -9256,7 +9333,11 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
ASSERT(!value->IsTheHole());
return MakePair(value, *receiver);
case IMMUTABLE_CHECK_INITIALIZED:
- return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
+ if (value->IsTheHole()) {
+ ASSERT((attributes & READ_ONLY) != 0);
+ value = isolate->heap()->undefined_value();
+ }
+ return MakePair(value, *receiver);
case MISSING_BINDING:
UNREACHABLE();
return MakePair(NULL, NULL);
@@ -9272,15 +9353,19 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
// GetProperty below can cause GC.
Handle<Object> receiver_handle(
object->IsGlobalObject()
- ? GlobalObject::cast(*object)->global_receiver()
+ ? Object::cast(isolate->heap()->undefined_value())
: object->IsJSProxy() ? static_cast<Object*>(*object)
: ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
isolate);
// No need to unhole the value here. This is taken care of by the
// GetProperty function.
- MaybeObject* value = object->GetProperty(*name);
- return MakePair(value, *receiver_handle);
+ Handle<Object> value;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, value,
+ Object::GetProperty(object, name),
+ MakePair(isolate->heap()->exception(), NULL));
+ return MakePair(*value, *receiver_handle);
}
if (throw_error) {
@@ -9297,26 +9382,24 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
}
-RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
+RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_LoadContextSlot) {
return LoadContextSlotHelper(args, isolate, true);
}
-RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
+RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_LoadContextSlotNoReferenceError) {
return LoadContextSlotHelper(args, isolate, false);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
+RUNTIME_FUNCTION(RuntimeHidden_StoreContextSlot) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
- Handle<Object> value(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
- CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
- StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
- ? kNonStrictMode : kStrictMode;
+ CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
int index;
PropertyAttributes attributes;
@@ -9327,7 +9410,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
&index,
&attributes,
&binding_flags);
- if (isolate->has_pending_exception()) return Failure::Exception();
+ if (isolate->has_pending_exception()) return isolate->heap()->exception();
if (index >= 0) {
// The property was found in a context slot.
@@ -9343,7 +9426,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
if ((attributes & READ_ONLY) == 0) {
// Context is a fixed array and set cannot fail.
context->set(index, *value);
- } else if (strict_mode == kStrictMode) {
+ } else if (strict_mode == STRICT) {
// Setting read only property in strict mode.
Handle<Object> error =
isolate->factory()->NewTypeError("strict_cannot_assign",
@@ -9365,25 +9448,25 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
// The property was not found.
ASSERT(attributes == ABSENT);
- if (strict_mode == kStrictMode) {
+ if (strict_mode == STRICT) {
// Throw in strict mode (assignment to undefined variable).
Handle<Object> error =
isolate->factory()->NewReferenceError(
"not_defined", HandleVector(&name, 1));
return isolate->Throw(*error);
}
- // In non-strict mode, the property is added to the global object.
+ // In sloppy mode, the property is added to the global object.
attributes = NONE;
object = Handle<JSReceiver>(isolate->context()->global_object());
}
// Set the property if it's not read only or doesn't yet exist.
if ((attributes & READ_ONLY) == 0 ||
- (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
- RETURN_IF_EMPTY_HANDLE(
+ (JSReceiver::GetOwnPropertyAttributes(object, name) == ABSENT)) {
+ RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
- } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
+ } else if (strict_mode == STRICT && (attributes & READ_ONLY) != 0) {
// Setting read only property in strict mode.
Handle<Object> error =
isolate->factory()->NewTypeError(
@@ -9394,7 +9477,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
+RUNTIME_FUNCTION(RuntimeHidden_Throw) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -9402,7 +9485,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
+RUNTIME_FUNCTION(RuntimeHidden_ReThrow) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -9410,18 +9493,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
+RUNTIME_FUNCTION(RuntimeHidden_PromoteScheduledException) {
SealHandleScope shs(isolate);
- ASSERT_EQ(0, args.length());
+ ASSERT(args.length() == 0);
return isolate->PromoteScheduledException();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
+RUNTIME_FUNCTION(RuntimeHidden_ThrowReferenceError) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
-
- Handle<Object> name(args[0], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
Handle<Object> reference_error =
isolate->factory()->NewReferenceError("not_defined",
HandleVector(&name, 1));
@@ -9429,7 +9511,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowNotDateError) {
+RUNTIME_FUNCTION(RuntimeHidden_ThrowNotDateError) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
return isolate->Throw(*isolate->factory()->NewTypeError(
@@ -9437,38 +9519,28 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowNotDateError) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_SMI_ARG_CHECKED(message_id, 0);
- const char* message = GetBailoutReason(
- static_cast<BailoutReason>(message_id));
- Handle<Name> message_handle =
- isolate->factory()->NewStringFromAscii(CStrVector(message));
- return isolate->Throw(*message_handle);
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
+RUNTIME_FUNCTION(RuntimeHidden_StackGuard) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
// First check if this is a real stack overflow.
- if (isolate->stack_guard()->IsStackOverflow()) {
+ StackLimitCheck check(isolate);
+ if (check.JsHasOverflowed()) {
return isolate->StackOverflow();
}
- return Execution::HandleStackGuardInterrupt(isolate);
+ return isolate->stack_guard()->HandleInterrupts();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TryInstallRecompiledCode) {
+RUNTIME_FUNCTION(RuntimeHidden_TryInstallOptimizedCode) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
// First check if this is a real stack overflow.
- if (isolate->stack_guard()->IsStackOverflow()) {
+ StackLimitCheck check(isolate);
+ if (check.JsHasOverflowed()) {
SealHandleScope shs(isolate);
return isolate->StackOverflow();
}
@@ -9479,10 +9551,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TryInstallRecompiledCode) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
+RUNTIME_FUNCTION(RuntimeHidden_Interrupt) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
- return Execution::HandleStackGuardInterrupt(isolate);
+ return isolate->stack_guard()->HandleInterrupts();
}
@@ -9515,7 +9587,7 @@ static void PrintTransition(Isolate* isolate, Object* result) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
+RUNTIME_FUNCTION(Runtime_TraceEnter) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
PrintTransition(isolate, NULL);
@@ -9523,14 +9595,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
+RUNTIME_FUNCTION(Runtime_TraceExit) {
SealHandleScope shs(isolate);
- PrintTransition(isolate, args[0]);
- return args[0]; // return TOS
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_CHECKED(Object, obj, 0);
+ PrintTransition(isolate, obj);
+ return obj; // return TOS
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
+RUNTIME_FUNCTION(Runtime_DebugPrint) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -9561,7 +9635,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
+RUNTIME_FUNCTION(Runtime_DebugTrace) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
isolate->PrintStack(stdout);
@@ -9569,45 +9643,45 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DateCurrentTime) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 0);
+ if (FLAG_log_timer_events) LOG(isolate, CurrentTimeEvent());
// According to ECMA-262, section 15.9.1, page 117, the precision of
// the number in a Date object representing a particular instant in
// time is milliseconds. Therefore, we floor the result of getting
// the OS time.
- double millis = floor(OS::TimeCurrentMillis());
- return isolate->heap()->NumberFromDouble(millis);
+ double millis = std::floor(OS::TimeCurrentMillis());
+ return *isolate->factory()->NewNumber(millis);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
+RUNTIME_FUNCTION(Runtime_DateParseString) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
-
CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
- FlattenString(str);
-
CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
+ RUNTIME_ASSERT(output->HasFastElements());
JSObject::EnsureCanContainHeapObjectElements(output);
RUNTIME_ASSERT(output->HasFastObjectElements());
+ Handle<FixedArray> output_array(FixedArray::cast(output->elements()));
+ RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
+ str = String::Flatten(str);
DisallowHeapAllocation no_gc;
- FixedArray* output_array = FixedArray::cast(output->elements());
- RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
bool result;
String::FlatContent str_content = str->GetFlatContent();
if (str_content.IsAscii()) {
result = DateParser::Parse(str_content.ToOneByteVector(),
- output_array,
+ *output_array,
isolate->unicode_cache());
} else {
ASSERT(str_content.IsTwoByte());
result = DateParser::Parse(str_content.ToUC16Vector(),
- output_array,
+ *output_array,
isolate->unicode_cache());
}
@@ -9619,65 +9693,86 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DateLocalTimezone) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
- const char* zone = OS::LocalTimezone(static_cast<double>(time));
- return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
+ RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs &&
+ x <= DateCache::kMaxTimeBeforeUTCInMs);
+ const char* zone =
+ isolate->date_cache()->LocalTimezone(static_cast<int64_t>(x));
+ Handle<String> result = isolate->factory()->NewStringFromUtf8(
+ CStrVector(zone)).ToHandleChecked();
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DateToUTC) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
+ RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs &&
+ x <= DateCache::kMaxTimeBeforeUTCInMs);
int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
- return isolate->heap()->NumberFromDouble(static_cast<double>(time));
+ return *isolate->factory()->NewNumber(static_cast<double>(time));
+}
+
+
+RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
+ HandleScope hs(isolate);
+ ASSERT(args.length() == 0);
+ if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
+ Handle<FixedArray> date_cache_version =
+ isolate->factory()->NewFixedArray(1, TENURED);
+ date_cache_version->set(0, Smi::FromInt(0));
+ isolate->eternal_handles()->CreateSingleton(
+ isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
+ }
+ Handle<FixedArray> date_cache_version =
+ Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
+ EternalHandles::DATE_CACHE_VERSION));
+ // Return result as a JS array.
+ Handle<JSObject> result =
+ isolate->factory()->NewJSObject(isolate->array_function());
+ JSArray::SetContent(Handle<JSArray>::cast(result), date_cache_version);
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
+RUNTIME_FUNCTION(Runtime_GlobalReceiver) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* global = args[0];
+ CONVERT_ARG_CHECKED(Object, global, 0);
if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
return JSGlobalObject::cast(global)->global_receiver();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAttachedGlobal) {
+RUNTIME_FUNCTION(Runtime_IsAttachedGlobal) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- Object* global = args[0];
+ CONVERT_ARG_CHECKED(Object, global, 0);
if (!global->IsJSGlobalObject()) return isolate->heap()->false_value();
return isolate->heap()->ToBoolean(
!JSGlobalObject::cast(global)->IsDetached());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
+RUNTIME_FUNCTION(Runtime_ParseJson) {
HandleScope scope(isolate);
- ASSERT_EQ(1, args.length());
+ ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
- source = Handle<String>(FlattenGetString(source));
+ source = String::Flatten(source);
// Optimized fast case where we only have ASCII characters.
Handle<Object> result;
- if (source->IsSeqOneByteString()) {
- result = JsonParser<true>::Parse(source);
- } else {
- result = JsonParser<false>::Parse(source);
- }
- if (result.is_null()) {
- // Syntax error or stack overflow in scanner.
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ source->IsSeqOneByteString() ? JsonParser<true>::Parse(source)
+ : JsonParser<false>::Parse(source));
return *result;
}
@@ -9699,15 +9794,73 @@ bool CodeGenerationFromStringsAllowed(Isolate* isolate,
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
+// Walk up the stack expecting:
+// - Runtime_CompileString
+// - JSFunction callee (eval, Function constructor, etc)
+// - call() (maybe)
+// - apply() (maybe)
+// - bind() (maybe)
+// - JSFunction caller (maybe)
+//
+// return true if the caller has the same security token as the callee
+// or if an exit frame was hit, in which case allow it through, as it could
+// have come through the api.
+static bool TokensMatchForCompileString(Isolate* isolate) {
+ MaybeHandle<JSFunction> callee;
+ bool exit_handled = true;
+ bool tokens_match = true;
+ bool done = false;
+ for (StackFrameIterator it(isolate); !it.done() && !done; it.Advance()) {
+ StackFrame* raw_frame = it.frame();
+ if (!raw_frame->is_java_script()) {
+ if (raw_frame->is_exit()) exit_handled = false;
+ continue;
+ }
+ JavaScriptFrame* outer_frame = JavaScriptFrame::cast(raw_frame);
+ List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
+ outer_frame->Summarize(&frames);
+ for (int i = frames.length() - 1; i >= 0 && !done; --i) {
+ FrameSummary& frame = frames[i];
+ Handle<JSFunction> fun = frame.function();
+ // Capture the callee function.
+ if (callee.is_null()) {
+ callee = fun;
+ exit_handled = true;
+ continue;
+ }
+ // Exit condition.
+ Handle<Context> context(callee.ToHandleChecked()->context());
+ if (!fun->context()->HasSameSecurityTokenAs(*context)) {
+ tokens_match = false;
+ done = true;
+ continue;
+ }
+ // Skip bound functions in correct origin.
+ if (fun->shared()->bound()) {
+ exit_handled = true;
+ continue;
+ }
+ done = true;
+ }
+ }
+ return !exit_handled || tokens_match;
+}
+
+
+RUNTIME_FUNCTION(Runtime_CompileString) {
HandleScope scope(isolate);
- ASSERT_EQ(2, args.length());
+ ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
// Extract native context.
Handle<Context> context(isolate->context()->native_context());
+ // Filter cross security context calls.
+ if (!TokensMatchForCompileString(isolate)) {
+ return isolate->heap()->undefined_value();
+ }
+
// Check if native context allows code generation from
// strings. Throw an exception if it doesn't.
if (context->allow_code_gen_from_strings()->IsFalse() &&
@@ -9721,13 +9874,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
// Compile source string in the native context.
ParseRestriction restriction = function_literal_only
? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
- Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
- source, context, true, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
- RETURN_IF_EMPTY_HANDLE(isolate, shared);
- Handle<JSFunction> fun =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
- context,
- NOT_TENURED);
+ Handle<JSFunction> fun;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, fun,
+ Compiler::GetFunctionFromEval(
+ source, context, SLOPPY, restriction, RelocInfo::kNoPosition));
return *fun;
}
@@ -9735,7 +9886,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
static ObjectPair CompileGlobalEval(Isolate* isolate,
Handle<String> source,
Handle<Object> receiver,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position) {
Handle<Context> context = Handle<Context>(isolate->context());
Handle<Context> native_context = Handle<Context>(context->native_context());
@@ -9748,28 +9899,23 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
native_context->ErrorMessageForCodeGenerationFromStrings();
isolate->Throw(*isolate->factory()->NewEvalError(
"code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
- return MakePair(Failure::Exception(), NULL);
+ return MakePair(isolate->heap()->exception(), NULL);
}
// Deal with a normal eval call with a string argument. Compile it
// and return the compiled function bound in the local context.
- Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
- source,
- context,
- context->IsNativeContext(),
- language_mode,
- NO_PARSE_RESTRICTION,
- scope_position);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, shared,
- MakePair(Failure::Exception(), NULL));
- Handle<JSFunction> compiled =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(
- shared, context, NOT_TENURED);
+ static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
+ Handle<JSFunction> compiled;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, compiled,
+ Compiler::GetFunctionFromEval(
+ source, context, strict_mode, restriction, scope_position),
+ MakePair(isolate->heap()->exception(), NULL));
return MakePair(*compiled, *receiver);
}
-RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
+RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_ResolvePossiblyDirectEval) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
@@ -9782,65 +9928,50 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
// the first argument without doing anything).
if (*callee != isolate->native_context()->global_eval_fun() ||
!args[1]->IsString()) {
- return MakePair(*callee, isolate->heap()->the_hole_value());
+ return MakePair(*callee, isolate->heap()->undefined_value());
}
- CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
+ ASSERT(args[3]->IsSmi());
+ ASSERT(args.smi_at(3) == SLOPPY || args.smi_at(3) == STRICT);
+ StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(3));
ASSERT(args[4]->IsSmi());
return CompileGlobalEval(isolate,
args.at<String>(1),
args.at<Object>(2),
- language_mode,
+ strict_mode,
args.smi_at(4));
}
-// Allocate a block of memory in the given space (filled with a filler).
-// Used as a fall-back for generated code when the space is full.
-static MaybeObject* Allocate(Isolate* isolate,
- int size,
- bool double_align,
- AllocationSpace space) {
- Heap* heap = isolate->heap();
- RUNTIME_ASSERT(IsAligned(size, kPointerSize));
- RUNTIME_ASSERT(size > 0);
- RUNTIME_ASSERT(size <= heap->MaxRegularSpaceAllocationSize());
- HeapObject* allocation;
- { MaybeObject* maybe_allocation = heap->AllocateRaw(size, space, space);
- if (!maybe_allocation->To(&allocation)) return maybe_allocation;
- }
-#ifdef DEBUG
- MemoryChunk* chunk = MemoryChunk::FromAddress(allocation->address());
- ASSERT(chunk->owner()->identity() == space);
-#endif
- heap->CreateFillerObjectAt(allocation->address(), size);
- return allocation;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_AllocateInNewSpace) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_SMI_ARG_CHECKED(size, 0);
- return Allocate(isolate, size, false, NEW_SPACE);
+ RUNTIME_ASSERT(IsAligned(size, kPointerSize));
+ RUNTIME_ASSERT(size > 0);
+ RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
+ return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInTargetSpace) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(RuntimeHidden_AllocateInTargetSpace) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_SMI_ARG_CHECKED(size, 0);
CONVERT_SMI_ARG_CHECKED(flags, 1);
+ RUNTIME_ASSERT(IsAligned(size, kPointerSize));
+ RUNTIME_ASSERT(size > 0);
+ RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
bool double_align = AllocateDoubleAlignFlag::decode(flags);
AllocationSpace space = AllocateTargetSpace::decode(flags);
- return Allocate(isolate, size, double_align, space);
+ return *isolate->factory()->NewFillerObject(size, double_align, space);
}
// Push an object unto an array of objects if it is not already in the
// array. Returns true if the element was pushed on the stack and
// false otherwise.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
+RUNTIME_FUNCTION(Runtime_PushIfAbsent) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
@@ -9853,10 +9984,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
}
// Strict not needed. Used for cycle detection in Array join implementation.
- RETURN_IF_EMPTY_HANDLE(isolate, JSObject::SetFastElement(array, length,
- element,
- kNonStrictMode,
- true));
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate,
+ JSObject::SetFastElement(array, length, element, SLOPPY, true));
return isolate->heap()->true_value();
}
@@ -9904,14 +10034,14 @@ class ArrayConcatVisitor {
// getters on the arrays increasing the length of later arrays
// during iteration.
// This shouldn't happen in anything but pathological cases.
- SetDictionaryMode(index);
+ SetDictionaryMode();
// Fall-through to dictionary mode.
}
ASSERT(!fast_elements_);
Handle<SeededNumberDictionary> dict(
SeededNumberDictionary::cast(*storage_));
Handle<SeededNumberDictionary> result =
- isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
+ SeededNumberDictionary::AtNumberPut(dict, index, elm);
if (!result.is_identical_to(dict)) {
// Dictionary needed to grow.
clear_storage();
@@ -9925,6 +10055,14 @@ class ArrayConcatVisitor {
} else {
index_offset_ += delta;
}
+ // If the initial length estimate was off (see special case in visit()),
+ // but the array blowing the limit didn't contain elements beyond the
+ // provided-for index range, go to dictionary mode now.
+ if (fast_elements_ &&
+ index_offset_ >
+ static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
+ SetDictionaryMode();
+ }
}
bool exceeds_array_limit() {
@@ -9935,14 +10073,9 @@ class ArrayConcatVisitor {
Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
Handle<Object> length =
isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
- Handle<Map> map;
- if (fast_elements_) {
- map = isolate_->factory()->GetElementsTransitionMap(array,
- FAST_HOLEY_ELEMENTS);
- } else {
- map = isolate_->factory()->GetElementsTransitionMap(array,
- DICTIONARY_ELEMENTS);
- }
+ Handle<Map> map = JSObject::GetElementsTransitionMap(
+ array,
+ fast_elements_ ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
array->set_map(*map);
array->set_length(*length);
array->set_elements(*storage_);
@@ -9951,19 +10084,18 @@ class ArrayConcatVisitor {
private:
// Convert storage to dictionary mode.
- void SetDictionaryMode(uint32_t index) {
+ void SetDictionaryMode() {
ASSERT(fast_elements_);
Handle<FixedArray> current_storage(*storage_);
Handle<SeededNumberDictionary> slow_storage(
- isolate_->factory()->NewSeededNumberDictionary(
- current_storage->length()));
+ SeededNumberDictionary::New(isolate_, current_storage->length()));
uint32_t current_length = static_cast<uint32_t>(current_storage->length());
for (uint32_t i = 0; i < current_length; i++) {
HandleScope loop_scope(isolate_);
Handle<Object> element(current_storage->get(i), isolate_);
if (!element->IsTheHole()) {
Handle<SeededNumberDictionary> new_storage =
- isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
+ SeededNumberDictionary::AtNumberPut(slow_storage, i, element);
if (!new_storage.is_identical_to(slow_storage)) {
slow_storage = loop_scope.CloseAndEscape(new_storage);
}
@@ -9975,8 +10107,7 @@ class ArrayConcatVisitor {
}
inline void clear_storage() {
- isolate_->global_handles()->Destroy(
- Handle<Object>::cast(storage_).location());
+ GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
}
inline void set_storage(FixedArray* storage) {
@@ -10041,16 +10172,13 @@ static uint32_t EstimateElementCount(Handle<JSArray> array) {
}
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- case EXTERNAL_BYTE_ELEMENTS:
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
- case EXTERNAL_SHORT_ELEMENTS:
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
- case EXTERNAL_INT_ELEMENTS:
- case EXTERNAL_UNSIGNED_INT_ELEMENTS:
- case EXTERNAL_FLOAT_ELEMENTS:
- case EXTERNAL_DOUBLE_ELEMENTS:
- case EXTERNAL_PIXEL_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
+#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+ case EXTERNAL_##TYPE##_ELEMENTS: \
+ case TYPE##_ELEMENTS: \
+
+ TYPED_ARRAYS(TYPED_ARRAY_CASE)
+#undef TYPED_ARRAY_CASE
// External arrays are always dense.
return length;
}
@@ -10158,51 +10286,16 @@ static void CollectElementIndices(Handle<JSObject> object,
default: {
int dense_elements_length;
switch (kind) {
- case EXTERNAL_PIXEL_ELEMENTS: {
- dense_elements_length =
- ExternalPixelArray::cast(object->elements())->length();
- break;
- }
- case EXTERNAL_BYTE_ELEMENTS: {
- dense_elements_length =
- ExternalByteArray::cast(object->elements())->length();
- break;
- }
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
- dense_elements_length =
- ExternalUnsignedByteArray::cast(object->elements())->length();
- break;
- }
- case EXTERNAL_SHORT_ELEMENTS: {
- dense_elements_length =
- ExternalShortArray::cast(object->elements())->length();
- break;
- }
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
- dense_elements_length =
- ExternalUnsignedShortArray::cast(object->elements())->length();
- break;
- }
- case EXTERNAL_INT_ELEMENTS: {
- dense_elements_length =
- ExternalIntArray::cast(object->elements())->length();
- break;
- }
- case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
- dense_elements_length =
- ExternalUnsignedIntArray::cast(object->elements())->length();
- break;
- }
- case EXTERNAL_FLOAT_ELEMENTS: {
- dense_elements_length =
- ExternalFloatArray::cast(object->elements())->length();
- break;
- }
- case EXTERNAL_DOUBLE_ELEMENTS: {
- dense_elements_length =
- ExternalDoubleArray::cast(object->elements())->length();
- break;
+#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+ case EXTERNAL_##TYPE##_ELEMENTS: { \
+ dense_elements_length = \
+ External##Type##Array::cast(object->elements())->length(); \
+ break; \
}
+
+ TYPED_ARRAYS(TYPED_ARRAY_CASE)
+#undef TYPED_ARRAY_CASE
+
default:
UNREACHABLE();
dense_elements_length = 0;
@@ -10264,8 +10357,10 @@ static bool IterateElements(Isolate* isolate,
} else if (JSReceiver::HasElement(receiver, j)) {
// Call GetElement on receiver, not its prototype, or getters won't
// have the correct receiver.
- element_value = Object::GetElement(isolate, receiver, j);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, element_value,
+ Object::GetElement(isolate, receiver, j),
+ false);
visitor->visit(j, element_value);
}
}
@@ -10273,8 +10368,14 @@ static bool IterateElements(Isolate* isolate,
}
case FAST_HOLEY_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS: {
+ // Empty array is FixedArray but not FixedDoubleArray.
+ if (length == 0) break;
// Run through the elements FixedArray and use HasElement and GetElement
// to check the prototype for missing elements.
+ if (receiver->elements()->IsFixedArray()) {
+ ASSERT(receiver->elements()->length() == 0);
+ break;
+ }
Handle<FixedDoubleArray> elements(
FixedDoubleArray::cast(receiver->elements()));
int fast_length = static_cast<int>(length);
@@ -10289,9 +10390,11 @@ static bool IterateElements(Isolate* isolate,
} else if (JSReceiver::HasElement(receiver, j)) {
// Call GetElement on receiver, not its prototype, or getters won't
// have the correct receiver.
- Handle<Object> element_value =
- Object::GetElement(isolate, receiver, j);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
+ Handle<Object> element_value;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, element_value,
+ Object::GetElement(isolate, receiver, j),
+ false);
visitor->visit(j, element_value);
}
}
@@ -10309,8 +10412,11 @@ static bool IterateElements(Isolate* isolate,
while (j < n) {
HandleScope loop_scope(isolate);
uint32_t index = indices[j];
- Handle<Object> element = Object::GetElement(isolate, receiver, index);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
+ Handle<Object> element;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, element,
+ Object::GetElement(isolate, receiver, index),
+ false);
visitor->visit(index, element);
// Skip to next different index (i.e., omit duplicates).
do {
@@ -10319,8 +10425,8 @@ static bool IterateElements(Isolate* isolate,
}
break;
}
- case EXTERNAL_PIXEL_ELEMENTS: {
- Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
+ case EXTERNAL_UINT8_CLAMPED_ELEMENTS: {
+ Handle<ExternalUint8ClampedArray> pixels(ExternalUint8ClampedArray::cast(
receiver->elements()));
for (uint32_t j = 0; j < length; j++) {
Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
@@ -10328,43 +10434,43 @@ static bool IterateElements(Isolate* isolate,
}
break;
}
- case EXTERNAL_BYTE_ELEMENTS: {
- IterateExternalArrayElements<ExternalByteArray, int8_t>(
+ case EXTERNAL_INT8_ELEMENTS: {
+ IterateExternalArrayElements<ExternalInt8Array, int8_t>(
isolate, receiver, true, true, visitor);
break;
}
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
- IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
+ case EXTERNAL_UINT8_ELEMENTS: {
+ IterateExternalArrayElements<ExternalUint8Array, uint8_t>(
isolate, receiver, true, true, visitor);
break;
}
- case EXTERNAL_SHORT_ELEMENTS: {
- IterateExternalArrayElements<ExternalShortArray, int16_t>(
+ case EXTERNAL_INT16_ELEMENTS: {
+ IterateExternalArrayElements<ExternalInt16Array, int16_t>(
isolate, receiver, true, true, visitor);
break;
}
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
- IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
+ case EXTERNAL_UINT16_ELEMENTS: {
+ IterateExternalArrayElements<ExternalUint16Array, uint16_t>(
isolate, receiver, true, true, visitor);
break;
}
- case EXTERNAL_INT_ELEMENTS: {
- IterateExternalArrayElements<ExternalIntArray, int32_t>(
+ case EXTERNAL_INT32_ELEMENTS: {
+ IterateExternalArrayElements<ExternalInt32Array, int32_t>(
isolate, receiver, true, false, visitor);
break;
}
- case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
- IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
+ case EXTERNAL_UINT32_ELEMENTS: {
+ IterateExternalArrayElements<ExternalUint32Array, uint32_t>(
isolate, receiver, true, false, visitor);
break;
}
- case EXTERNAL_FLOAT_ELEMENTS: {
- IterateExternalArrayElements<ExternalFloatArray, float>(
+ case EXTERNAL_FLOAT32_ELEMENTS: {
+ IterateExternalArrayElements<ExternalFloat32Array, float>(
isolate, receiver, false, false, visitor);
break;
}
- case EXTERNAL_DOUBLE_ELEMENTS: {
- IterateExternalArrayElements<ExternalDoubleArray, double>(
+ case EXTERNAL_FLOAT64_ELEMENTS: {
+ IterateExternalArrayElements<ExternalFloat64Array, double>(
isolate, receiver, false, false, visitor);
break;
}
@@ -10383,7 +10489,7 @@ static bool IterateElements(Isolate* isolate,
* TODO(581): Fix non-compliance for very large concatenations and update to
* following the ECMAScript 5 specification.
*/
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
+RUNTIME_FUNCTION(Runtime_ArrayConcat) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 1);
@@ -10450,12 +10556,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
// dictionary.
bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
- Handle<FixedArray> storage;
- if (fast_case) {
- if (kind == FAST_DOUBLE_ELEMENTS) {
+ if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
+ Handle<FixedArrayBase> storage =
+ isolate->factory()->NewFixedDoubleArray(estimate_result_length);
+ int j = 0;
+ if (estimate_result_length > 0) {
Handle<FixedDoubleArray> double_storage =
- isolate->factory()->NewFixedDoubleArray(estimate_result_length);
- int j = 0;
+ Handle<FixedDoubleArray>::cast(storage);
bool failure = false;
for (int i = 0; i < argument_count; i++) {
Handle<Object> obj(elements->get(i), isolate);
@@ -10471,8 +10578,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
switch (array->map()->elements_kind()) {
case FAST_HOLEY_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS: {
- // Empty fixed array indicates that there are no elements.
- if (array->elements()->IsFixedArray()) break;
+ // Empty array is FixedArray but not FixedDoubleArray.
+ if (length == 0) break;
FixedDoubleArray* elements =
FixedDoubleArray::cast(array->elements());
for (uint32_t i = 0; i < length; i++) {
@@ -10511,15 +10618,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
}
if (failure) break;
}
- Handle<JSArray> array = isolate->factory()->NewJSArray(0);
- Smi* length = Smi::FromInt(j);
- Handle<Map> map;
- map = isolate->factory()->GetElementsTransitionMap(array, kind);
- array->set_map(*map);
- array->set_length(length);
- array->set_elements(*double_storage);
- return *array;
}
+ Handle<JSArray> array = isolate->factory()->NewJSArray(0);
+ Smi* length = Smi::FromInt(j);
+ Handle<Map> map;
+ map = JSObject::GetElementsTransitionMap(array, kind);
+ array->set_map(*map);
+ array->set_length(length);
+ array->set_elements(*storage);
+ return *array;
+ }
+
+ Handle<FixedArray> storage;
+ if (fast_case) {
// The backing storage array must have non-existing elements to preserve
// holes across concat operations.
storage = isolate->factory()->NewFixedArrayWithHoles(
@@ -10529,7 +10640,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
uint32_t at_least_space_for = estimate_nof_elements +
(estimate_nof_elements >> 2);
storage = Handle<FixedArray>::cast(
- isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
+ SeededNumberDictionary::New(isolate, at_least_space_for));
}
ArrayConcatVisitor visitor(isolate, storage, fast_case);
@@ -10539,7 +10650,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
if (obj->IsJSArray()) {
Handle<JSArray> array = Handle<JSArray>::cast(obj);
if (!IterateElements(isolate, array, &visitor)) {
- return Failure::Exception();
+ return isolate->heap()->exception();
}
} else {
visitor.visit(0, obj);
@@ -10558,7 +10669,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
// This will not allocate (flatten the string), but it may run
// very slowly for very deeply nested ConsStrings. For debugging use only.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
+RUNTIME_FUNCTION(Runtime_GlobalPrint) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -10578,7 +10689,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
// and are followed by non-existing element. Does not change the length
// property.
// Returns the number of non-undefined elements collected.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
+// Returns -1 if hole removal is not supported by this method.
+RUNTIME_FUNCTION(Runtime_RemoveArrayHoles) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@@ -10588,44 +10700,39 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
// Move contents of argument 0 (an array) to argument 1 (an array)
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_MoveArrayContents) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(JSArray, from, 0);
- CONVERT_ARG_CHECKED(JSArray, to, 1);
- from->ValidateElements();
- to->ValidateElements();
- FixedArrayBase* new_elements = from->elements();
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, from, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, to, 1);
+ JSObject::ValidateElements(from);
+ JSObject::ValidateElements(to);
+
+ Handle<FixedArrayBase> new_elements(from->elements());
ElementsKind from_kind = from->GetElementsKind();
- MaybeObject* maybe_new_map;
- maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
- Object* new_map;
- if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
- to->set_map_and_elements(Map::cast(new_map), new_elements);
+ Handle<Map> new_map = JSObject::GetElementsTransitionMap(to, from_kind);
+ JSObject::SetMapAndElements(to, new_map, new_elements);
to->set_length(from->length());
- Object* obj;
- { MaybeObject* maybe_obj = from->ResetElements();
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
+
+ JSObject::ResetElements(from);
from->set_length(Smi::FromInt(0));
- to->ValidateElements();
- return to;
+
+ JSObject::ValidateElements(to);
+ return *to;
}
// How many elements does this object/array have?
-RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
+RUNTIME_FUNCTION(Runtime_EstimateNumberOfElements) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(JSObject, object, 0);
+ CONVERT_ARG_CHECKED(JSArray, object, 0);
HeapObject* elements = object->elements();
if (elements->IsDictionary()) {
int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
return Smi::FromInt(result);
- } else if (object->IsJSArray()) {
- return JSArray::cast(object)->length();
} else {
- return Smi::FromInt(FixedArray::cast(elements)->length());
+ return object->length();
}
}
@@ -10635,7 +10742,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
// or undefined) or a number representing the positive length of an interval
// starting at index 0.
// Intervals can span over some keys that are not in the object.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
+RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
@@ -10652,10 +10759,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
}
Handle<JSObject> current = Handle<JSObject>::cast(p);
Handle<FixedArray> current_keys =
- isolate->factory()->NewFixedArray(
- current->NumberOfLocalElements(NONE));
- current->GetLocalElementKeys(*current_keys, NONE);
- keys = UnionOfKeys(keys, current_keys);
+ isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE));
+ current->GetOwnElementKeys(*current_keys, NONE);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, keys, FixedArray::UnionOfKeys(keys, current_keys));
}
// Erase any keys >= length.
// TODO(adamk): Remove this step when the contract of %GetArrayKeys
@@ -10665,15 +10772,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
}
return *isolate->factory()->NewJSArrayWithElements(keys);
} else {
- ASSERT(array->HasFastSmiOrObjectElements() ||
- array->HasFastDoubleElements());
+ RUNTIME_ASSERT(array->HasFastSmiOrObjectElements() ||
+ array->HasFastDoubleElements());
uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
+RUNTIME_FUNCTION(Runtime_LookupAccessor) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
@@ -10681,18 +10788,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
CONVERT_SMI_ARG_CHECKED(flag, 2);
AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
- Handle<Object> result =
- JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
return *result;
}
-#ifdef ENABLE_DEBUGGER_SUPPORT
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
+RUNTIME_FUNCTION(Runtime_DebugBreak) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
- return Execution::DebugBreakHelper(isolate);
+ isolate->debug()->HandleDebugBreak();
+ return isolate->heap()->undefined_value();
}
@@ -10712,86 +10820,72 @@ static StackFrame::Id UnwrapFrameId(int wrapped) {
// args[0]: debug event listener function to set or null or undefined for
// clearing the event listener function
// args[1]: object supplied during callback
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
+RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
RUNTIME_ASSERT(args[0]->IsJSFunction() ||
args[0]->IsUndefined() ||
args[0]->IsNull());
- Handle<Object> callback = args.at<Object>(0);
- Handle<Object> data = args.at<Object>(1);
- isolate->debugger()->SetEventListener(callback, data);
+ CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
+ isolate->debug()->SetEventListener(callback, data);
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
+RUNTIME_FUNCTION(Runtime_Break) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
- isolate->stack_guard()->DebugBreak();
+ isolate->stack_guard()->RequestDebugBreak();
return isolate->heap()->undefined_value();
}
-static MaybeObject* DebugLookupResultValue(Heap* heap,
- Object* receiver,
- Name* name,
- LookupResult* result,
- bool* caught_exception) {
- Object* value;
+static Handle<Object> DebugLookupResultValue(Isolate* isolate,
+ Handle<Object> receiver,
+ Handle<Name> name,
+ LookupResult* result,
+ bool* has_caught = NULL) {
+ Handle<Object> value = isolate->factory()->undefined_value();
+ if (!result->IsFound()) return value;
switch (result->type()) {
case NORMAL:
- value = result->holder()->GetNormalizedProperty(result);
- if (value->IsTheHole()) {
- return heap->undefined_value();
- }
- return value;
- case FIELD: {
- Object* value;
- MaybeObject* maybe_value =
- JSObject::cast(result->holder())->FastPropertyAt(
- result->representation(),
- result->GetFieldIndex().field_index());
- if (!maybe_value->To(&value)) return maybe_value;
- if (value->IsTheHole()) {
- return heap->undefined_value();
- }
- return value;
- }
+ value = JSObject::GetNormalizedProperty(
+ handle(result->holder(), isolate), result);
+ break;
+ case FIELD:
+ value = JSObject::FastPropertyAt(handle(result->holder(), isolate),
+ result->representation(),
+ result->GetFieldIndex());
+ break;
case CONSTANT:
- return result->GetConstant();
+ return handle(result->GetConstant(), isolate);
case CALLBACKS: {
- Object* structure = result->GetCallbackObject();
- if (structure->IsForeign() || structure->IsAccessorInfo()) {
- Isolate* isolate = heap->isolate();
- HandleScope scope(isolate);
- Handle<Object> value = JSObject::GetPropertyWithCallback(
- handle(result->holder(), isolate),
- handle(receiver, isolate),
- handle(structure, isolate),
- handle(name, isolate));
- if (value.is_null()) {
- MaybeObject* exception = heap->isolate()->pending_exception();
- heap->isolate()->clear_pending_exception();
- if (caught_exception != NULL) *caught_exception = true;
- return exception;
+ Handle<Object> structure(result->GetCallbackObject(), isolate);
+ ASSERT(!structure->IsForeign());
+ if (structure->IsAccessorInfo()) {
+ MaybeHandle<Object> obj = JSObject::GetPropertyWithAccessor(
+ receiver, name, handle(result->holder(), isolate), structure);
+ if (!obj.ToHandle(&value)) {
+ value = handle(isolate->pending_exception(), isolate);
+ isolate->clear_pending_exception();
+ if (has_caught != NULL) *has_caught = true;
+ return value;
}
- return *value;
- } else {
- return heap->undefined_value();
}
+ break;
}
case INTERCEPTOR:
- case TRANSITION:
- return heap->undefined_value();
case HANDLER:
+ break;
case NONEXISTENT:
UNREACHABLE();
- return heap->undefined_value();
+ break;
}
- UNREACHABLE(); // keep the compiler happy
- return heap->undefined_value();
+ ASSERT(!value->IsTheHole() || result->IsReadOnly());
+ return value->IsTheHole()
+ ? Handle<Object>::cast(isolate->factory()->undefined_value()) : value;
}
@@ -10807,7 +10901,7 @@ static MaybeObject* DebugLookupResultValue(Heap* heap,
// 4: Setter function if defined
// Items 2-4 are only filled if the property has either a getter or a setter
// defined through __defineGetter__ and/or __defineSetter__.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
+RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -10822,7 +10916,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
// could have the assumption that its own native context is the current
// context and not some internal debugger context.
SaveContext save(isolate);
- if (isolate->debug()->InDebugger()) {
+ if (isolate->debug()->in_debug_scope()) {
isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
}
@@ -10838,27 +10932,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
uint32_t index;
if (name->AsArrayIndex(&index)) {
Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
- Object* element_or_char;
- { MaybeObject* maybe_element_or_char =
- Runtime::GetElementOrCharAt(isolate, obj, index);
- if (!maybe_element_or_char->ToObject(&element_or_char)) {
- return maybe_element_or_char;
- }
- }
- details->set(0, element_or_char);
+ Handle<Object> element_or_char;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, element_or_char,
+ Runtime::GetElementOrCharAt(isolate, obj, index));
+ details->set(0, *element_or_char);
details->set(
1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
return *isolate->factory()->NewJSArrayWithElements(details);
}
// Find the number of objects making up this.
- int length = LocalPrototypeChainLength(*obj);
+ int length = OwnPrototypeChainLength(*obj);
- // Try local lookup on each of the objects.
+ // Try own lookup on each of the objects.
Handle<JSObject> jsproto = obj;
for (int i = 0; i < length; i++) {
LookupResult result(isolate);
- jsproto->LocalLookup(*name, &result);
+ jsproto->LookupOwn(name, &result);
if (result.IsFound()) {
// LookupResult is not GC safe as it holds raw object pointers.
// GC can happen later in this code so put the required fields into
@@ -10868,29 +10959,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
result_callback_obj = Handle<Object>(result.GetCallbackObject(),
isolate);
}
- Smi* property_details = result.GetPropertyDetails().AsSmi();
- // DebugLookupResultValue can cause GC so details from LookupResult needs
- // to be copied to handles before this.
- bool caught_exception = false;
- Object* raw_value;
- { MaybeObject* maybe_raw_value =
- DebugLookupResultValue(isolate->heap(), *obj, *name,
- &result, &caught_exception);
- if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
- }
- Handle<Object> value(raw_value, isolate);
+
+
+ bool has_caught = false;
+ Handle<Object> value = DebugLookupResultValue(
+ isolate, obj, name, &result, &has_caught);
// If the callback object is a fixed array then it contains JavaScript
// getter and/or setter.
- bool hasJavaScriptAccessors = result.IsPropertyCallbacks() &&
- result_callback_obj->IsAccessorPair();
+ bool has_js_accessors = result.IsPropertyCallbacks() &&
+ result_callback_obj->IsAccessorPair();
Handle<FixedArray> details =
- isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
+ isolate->factory()->NewFixedArray(has_js_accessors ? 5 : 2);
details->set(0, *value);
- details->set(1, property_details);
- if (hasJavaScriptAccessors) {
+ details->set(1, result.GetPropertyDetails().AsSmi());
+ if (has_js_accessors) {
AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
- details->set(2, isolate->heap()->ToBoolean(caught_exception));
+ details->set(2, isolate->heap()->ToBoolean(has_caught));
details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
}
@@ -10906,7 +10991,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
+RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -10915,17 +11000,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
LookupResult result(isolate);
- obj->Lookup(*name, &result);
- if (result.IsFound()) {
- return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
- }
- return isolate->heap()->undefined_value();
+ obj->Lookup(name, &result);
+ return *DebugLookupResultValue(isolate, obj, name, &result);
}
// Return the property type calculated from the property details.
// args[0]: smi with property details.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
+RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
@@ -10935,7 +11017,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
// Return the property attribute calculated from the property details.
// args[0]: smi with property details.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
+RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
@@ -10945,7 +11027,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
// Return the property insertion index calculated from the property details.
// args[0]: smi with property details.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
+RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
@@ -10957,17 +11039,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
// Return property value from named interceptor.
// args[0]: object
// args[1]: property name
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
+RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
RUNTIME_ASSERT(obj->HasNamedInterceptor());
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
- PropertyAttributes attributes;
- Handle<Object> result =
- JSObject::GetPropertyWithInterceptor(obj, obj, name, &attributes);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ LookupIterator it(obj, name, obj);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, JSObject::GetProperty(&it));
return *result;
}
@@ -10975,42 +11057,40 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
// Return element value from indexed interceptor.
// args[0]: object
// args[1]: index
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
+RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
RUNTIME_ASSERT(obj->HasIndexedInterceptor());
CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, JSObject::GetElementWithInterceptor(obj, obj, index));
+ return *result;
+}
+
- return obj->GetElementWithInterceptor(*obj, index);
+static bool CheckExecutionState(Isolate* isolate, int break_id) {
+ return !isolate->debug()->debug_context().is_null() &&
+ isolate->debug()->break_id() != 0 &&
+ isolate->debug()->break_id() == break_id;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
+RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
SealHandleScope shs(isolate);
- ASSERT(args.length() >= 1);
+ ASSERT(args.length() == 1);
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
- // Check that the break id is valid.
- if (isolate->debug()->break_id() == 0 ||
- break_id != isolate->debug()->break_id()) {
- return isolate->Throw(
- isolate->heap()->illegal_execution_state_string());
- }
-
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
return isolate->heap()->true_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
+RUNTIME_FUNCTION(Runtime_GetFrameCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
-
- // Check arguments.
- Object* result;
- { MaybeObject* maybe_result = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
// Count all frames which are relevant to debugging stack trace.
int n = 0;
@@ -11144,16 +11224,12 @@ static SaveContext* FindSavedContextForFrame(Isolate* isolate,
// Arguments name, value
// Locals name, value
// Return value if any
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
+RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
Heap* heap = isolate->heap();
@@ -11201,31 +11277,44 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
ASSERT(*scope_info != ScopeInfo::Empty(isolate));
// Get the locals names and values into a temporary array.
- //
- // TODO(1240907): Hide compiler-introduced stack variables
- // (e.g. .result)? For users of the debugger, they will probably be
- // confusing.
+ int local_count = scope_info->LocalCount();
+ for (int slot = 0; slot < scope_info->LocalCount(); ++slot) {
+ // Hide compiler-introduced temporary variables, whether on the stack or on
+ // the context.
+ if (scope_info->LocalIsSynthetic(slot))
+ local_count--;
+ }
+
Handle<FixedArray> locals =
- isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
+ isolate->factory()->NewFixedArray(local_count * 2);
// Fill in the values of the locals.
+ int local = 0;
int i = 0;
for (; i < scope_info->StackLocalCount(); ++i) {
// Use the value from the stack.
- locals->set(i * 2, scope_info->LocalName(i));
- locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
+ if (scope_info->LocalIsSynthetic(i))
+ continue;
+ locals->set(local * 2, scope_info->LocalName(i));
+ locals->set(local * 2 + 1, frame_inspector.GetExpression(i));
+ local++;
}
- if (i < scope_info->LocalCount()) {
+ if (local < local_count) {
// Get the context containing declarations.
Handle<Context> context(
Context::cast(it.frame()->context())->declaration_context());
for (; i < scope_info->LocalCount(); ++i) {
+ if (scope_info->LocalIsSynthetic(i))
+ continue;
Handle<String> name(scope_info->LocalName(i));
VariableMode mode;
InitializationFlag init_flag;
- locals->set(i * 2, *name);
- locals->set(i * 2 + 1, context->get(
- scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
+ locals->set(local * 2, *name);
+ int context_slot_index =
+ ScopeInfo::ContextSlotIndex(scope_info, name, &mode, &init_flag);
+ Object* value = context->get(context_slot_index);
+ locals->set(local * 2 + 1, value);
+ local++;
}
}
@@ -11286,7 +11375,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex +
- 2 * (argument_count + scope_info->LocalCount()) +
+ 2 * (argument_count + local_count) +
(at_return ? 1 : 0);
Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
@@ -11301,7 +11390,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// Add the locals count
details->set(kFrameDetailsLocalCountIndex,
- Smi::FromInt(scope_info->LocalCount()));
+ Smi::FromInt(local_count));
// Add the source position.
if (position != RelocInfo::kNoPosition) {
@@ -11352,7 +11441,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
// Add locals name and value from the temporary copy from the function frame.
- for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
+ for (int i = 0; i < local_count * 2; i++) {
details->set(details_index++, locals->get(i));
}
@@ -11366,7 +11455,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// THE FRAME ITERATOR TO WRAP THE RECEIVER.
Handle<Object> receiver(it.frame()->receiver(), isolate);
if (!receiver->IsJSObject() &&
- shared->is_classic_mode() &&
+ shared->strict_mode() == SLOPPY &&
!function->IsBuiltin()) {
// If the receiver is not a JSObject and the function is not a
// builtin or strict-mode we have hit an optimization where a
@@ -11375,11 +11464,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// by creating correct wrapper object based on the calling frame's
// native context.
it.Advance();
- Handle<Context> calling_frames_native_context(
- Context::cast(Context::cast(it.frame()->context())->native_context()));
- ASSERT(!receiver->IsUndefined() && !receiver->IsNull());
- receiver =
- isolate->factory()->ToObject(receiver, calling_frames_native_context);
+ if (receiver->IsUndefined()) {
+ Context* context = function->context();
+ receiver = handle(context->global_object()->global_receiver());
+ } else {
+ ASSERT(!receiver->IsNull());
+ Context* context = Context::cast(it.frame()->context());
+ Handle<Context> native_context(Context::cast(context->native_context()));
+ receiver = Object::ToObject(
+ isolate, receiver, native_context).ToHandleChecked();
+ }
}
details->set(kFrameDetailsReceiverIndex, *receiver);
@@ -11388,9 +11482,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
+static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,
+ Handle<String> parameter_name) {
+ VariableMode mode;
+ InitializationFlag flag;
+ return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &flag) != -1;
+}
+
+
// Create a plain JSObject which materializes the local scope for the specified
// frame.
-static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
+MUST_USE_RESULT
+static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector(
Isolate* isolate,
Handle<JSObject> target,
Handle<JSFunction> function,
@@ -11400,38 +11503,34 @@ static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
// First fill all parameters.
for (int i = 0; i < scope_info->ParameterCount(); ++i) {
+ // Do not materialize the parameter if it is shadowed by a context local.
+ Handle<String> name(scope_info->ParameterName(i));
+ if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
+
+ HandleScope scope(isolate);
Handle<Object> value(i < frame_inspector->GetParametersCount()
? frame_inspector->GetParameter(i)
: isolate->heap()->undefined_value(),
isolate);
ASSERT(!value->IsTheHole());
- RETURN_IF_EMPTY_HANDLE_VALUE(
+ RETURN_ON_EXCEPTION(
isolate,
- Runtime::SetObjectProperty(isolate,
- target,
- Handle<String>(scope_info->ParameterName(i)),
- value,
- NONE,
- kNonStrictMode),
- Handle<JSObject>());
+ Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
+ JSObject);
}
// Second fill all stack locals.
for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
+ if (scope_info->LocalIsSynthetic(i)) continue;
+ Handle<String> name(scope_info->StackLocalName(i));
Handle<Object> value(frame_inspector->GetExpression(i), isolate);
if (value->IsTheHole()) continue;
- RETURN_IF_EMPTY_HANDLE_VALUE(
+ RETURN_ON_EXCEPTION(
isolate,
- Runtime::SetObjectProperty(
- isolate,
- target,
- Handle<String>(scope_info->StackLocalName(i)),
- value,
- NONE,
- kNonStrictMode),
- Handle<JSObject>());
+ Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
+ JSObject);
}
return target;
@@ -11455,28 +11554,35 @@ static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
// Parameters.
for (int i = 0; i < scope_info->ParameterCount(); ++i) {
+ // Shadowed parameters were not materialized.
+ Handle<String> name(scope_info->ParameterName(i));
+ if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
+
ASSERT(!frame->GetParameter(i)->IsTheHole());
HandleScope scope(isolate);
- Handle<Object> value = GetProperty(
- isolate, target, Handle<String>(scope_info->ParameterName(i)));
+ Handle<Object> value =
+ Object::GetPropertyOrElement(target, name).ToHandleChecked();
frame->SetParameterValue(i, *value);
}
// Stack locals.
for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
+ if (scope_info->LocalIsSynthetic(i)) continue;
if (frame->GetExpression(i)->IsTheHole()) continue;
HandleScope scope(isolate);
- Handle<Object> value = GetProperty(
- isolate, target, Handle<String>(scope_info->StackLocalName(i)));
+ Handle<Object> value = Object::GetPropertyOrElement(
+ target,
+ handle(scope_info->StackLocalName(i), isolate)).ToHandleChecked();
frame->SetExpression(i, *value);
}
}
-static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
- Handle<JSObject> target,
- Handle<JSFunction> function,
- JavaScriptFrame* frame) {
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext(
+ Isolate* isolate,
+ Handle<JSObject> target,
+ Handle<JSFunction> function,
+ JavaScriptFrame* frame) {
HandleScope scope(isolate);
Handle<SharedFunctionInfo> shared(function->shared());
Handle<ScopeInfo> scope_info(shared->scope_info());
@@ -11488,7 +11594,7 @@ static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
Handle<Context> function_context(frame_context->declaration_context());
if (!ScopeInfo::CopyContextLocalsToScopeObject(
scope_info, function_context, target)) {
- return Handle<JSObject>();
+ return MaybeHandle<JSObject>();
}
// Finally copy any properties from the function context extension.
@@ -11497,24 +11603,24 @@ static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
if (function_context->has_extension() &&
!function_context->IsNativeContext()) {
Handle<JSObject> ext(JSObject::cast(function_context->extension()));
- bool threw = false;
- Handle<FixedArray> keys =
- GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
- if (threw) return Handle<JSObject>();
+ Handle<FixedArray> keys;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, keys,
+ JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS),
+ JSObject);
for (int i = 0; i < keys->length(); i++) {
// Names of variables introduced by eval are strings.
ASSERT(keys->get(i)->IsString());
Handle<String> key(String::cast(keys->get(i)));
- RETURN_IF_EMPTY_HANDLE_VALUE(
+ Handle<Object> value;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value, Object::GetPropertyOrElement(ext, key), JSObject);
+ RETURN_ON_EXCEPTION(
isolate,
- Runtime::SetObjectProperty(isolate,
- target,
- key,
- GetProperty(isolate, ext, key),
- NONE,
- kNonStrictMode),
- Handle<JSObject>());
+ Runtime::SetObjectProperty(
+ isolate, target, key, value, NONE, SLOPPY),
+ JSObject);
}
}
}
@@ -11523,7 +11629,7 @@ static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
}
-static Handle<JSObject> MaterializeLocalScope(
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalScope(
Isolate* isolate,
JavaScriptFrame* frame,
int inlined_jsframe_index) {
@@ -11532,9 +11638,11 @@ static Handle<JSObject> MaterializeLocalScope(
Handle<JSObject> local_scope =
isolate->factory()->NewJSObject(isolate->object_function());
- local_scope = MaterializeStackLocalsWithFrameInspector(
- isolate, local_scope, function, &frame_inspector);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, local_scope, Handle<JSObject>());
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, local_scope,
+ MaterializeStackLocalsWithFrameInspector(
+ isolate, local_scope, function, &frame_inspector),
+ JSObject);
return MaterializeLocalContext(isolate, local_scope, function, frame);
}
@@ -11548,11 +11656,11 @@ static bool SetContextLocalValue(Isolate* isolate,
Handle<Object> new_value) {
for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
Handle<String> next_name(scope_info->ContextLocalName(i));
- if (variable_name->Equals(*next_name)) {
+ if (String::Equals(variable_name, next_name)) {
VariableMode mode;
InitializationFlag init_flag;
int context_index =
- scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
+ ScopeInfo::ContextSlotIndex(scope_info, next_name, &mode, &init_flag);
context->set(context_index, *new_value);
return true;
}
@@ -11580,7 +11688,8 @@ static bool SetLocalVariableValue(Isolate* isolate,
// Parameters.
for (int i = 0; i < scope_info->ParameterCount(); ++i) {
- if (scope_info->ParameterName(i)->Equals(*variable_name)) {
+ HandleScope scope(isolate);
+ if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) {
frame->SetParameterValue(i, *new_value);
// Argument might be shadowed in heap context, don't stop here.
default_result = true;
@@ -11589,7 +11698,8 @@ static bool SetLocalVariableValue(Isolate* isolate,
// Stack locals.
for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
- if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
+ HandleScope scope(isolate);
+ if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
frame->SetExpression(i, *new_value);
return true;
}
@@ -11614,8 +11724,7 @@ static bool SetLocalVariableValue(Isolate* isolate,
// We don't expect this to do anything except replacing
// property value.
Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
- NONE,
- kNonStrictMode);
+ NONE, SLOPPY).Assert();
return true;
}
}
@@ -11628,8 +11737,9 @@ static bool SetLocalVariableValue(Isolate* isolate,
// Create a plain JSObject which materializes the closure content for the
// context.
-static Handle<JSObject> MaterializeClosure(Isolate* isolate,
- Handle<Context> context) {
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeClosure(
+ Isolate* isolate,
+ Handle<Context> context) {
ASSERT(context->IsFunctionContext());
Handle<SharedFunctionInfo> shared(context->closure()->shared());
@@ -11643,29 +11753,31 @@ static Handle<JSObject> MaterializeClosure(Isolate* isolate,
// Fill all context locals to the context extension.
if (!ScopeInfo::CopyContextLocalsToScopeObject(
scope_info, context, closure_scope)) {
- return Handle<JSObject>();
+ return MaybeHandle<JSObject>();
}
// Finally copy any properties from the function context extension. This will
// be variables introduced by eval.
if (context->has_extension()) {
Handle<JSObject> ext(JSObject::cast(context->extension()));
- bool threw = false;
- Handle<FixedArray> keys =
- GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
- if (threw) return Handle<JSObject>();
+ Handle<FixedArray> keys;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, keys,
+ JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS), JSObject);
for (int i = 0; i < keys->length(); i++) {
+ HandleScope scope(isolate);
// Names of variables introduced by eval are strings.
ASSERT(keys->get(i)->IsString());
Handle<String> key(String::cast(keys->get(i)));
- RETURN_IF_EMPTY_HANDLE_VALUE(
+ Handle<Object> value;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value, Object::GetPropertyOrElement(ext, key), JSObject);
+ RETURN_ON_EXCEPTION(
isolate,
- Runtime::SetObjectProperty(isolate, closure_scope, key,
- GetProperty(isolate, ext, key),
- NONE,
- kNonStrictMode),
- Handle<JSObject>());
+ Runtime::SetObjectProperty(
+ isolate, closure_scope, key, value, NONE, SLOPPY),
+ JSObject);
}
}
@@ -11696,8 +11808,7 @@ static bool SetClosureVariableValue(Isolate* isolate,
if (JSReceiver::HasProperty(ext, variable_name)) {
// We don't expect this to do anything except replacing property value.
Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
- NONE,
- kNonStrictMode);
+ NONE, SLOPPY).Assert();
return true;
}
}
@@ -11708,20 +11819,20 @@ static bool SetClosureVariableValue(Isolate* isolate,
// Create a plain JSObject which materializes the scope for the specified
// catch context.
-static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
- Handle<Context> context) {
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeCatchScope(
+ Isolate* isolate,
+ Handle<Context> context) {
ASSERT(context->IsCatchContext());
Handle<String> name(String::cast(context->extension()));
Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
isolate);
Handle<JSObject> catch_scope =
isolate->factory()->NewJSObject(isolate->object_function());
- RETURN_IF_EMPTY_HANDLE_VALUE(
+ RETURN_ON_EXCEPTION(
isolate,
Runtime::SetObjectProperty(isolate, catch_scope, name, thrown_object,
- NONE,
- kNonStrictMode),
- Handle<JSObject>());
+ NONE, SLOPPY),
+ JSObject);
return catch_scope;
}
@@ -11732,7 +11843,7 @@ static bool SetCatchVariableValue(Isolate* isolate,
Handle<Object> new_value) {
ASSERT(context->IsCatchContext());
Handle<String> name(String::cast(context->extension()));
- if (!name->Equals(*variable_name)) {
+ if (!String::Equals(name, variable_name)) {
return false;
}
context->set(Context::THROWN_OBJECT_INDEX, *new_value);
@@ -11742,7 +11853,7 @@ static bool SetCatchVariableValue(Isolate* isolate,
// Create a plain JSObject which materializes the block scope for the specified
// block context.
-static Handle<JSObject> MaterializeBlockScope(
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope(
Isolate* isolate,
Handle<Context> context) {
ASSERT(context->IsBlockContext());
@@ -11756,7 +11867,7 @@ static Handle<JSObject> MaterializeBlockScope(
// Fill all context locals.
if (!ScopeInfo::CopyContextLocalsToScopeObject(
scope_info, context, block_scope)) {
- return Handle<JSObject>();
+ return MaybeHandle<JSObject>();
}
return block_scope;
@@ -11765,7 +11876,7 @@ static Handle<JSObject> MaterializeBlockScope(
// Create a plain JSObject which materializes the module scope for the specified
// module context.
-static Handle<JSObject> MaterializeModuleScope(
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope(
Isolate* isolate,
Handle<Context> context) {
ASSERT(context->IsModuleContext());
@@ -11779,7 +11890,7 @@ static Handle<JSObject> MaterializeModuleScope(
// Fill all context locals.
if (!ScopeInfo::CopyContextLocalsToScopeObject(
scope_info, context, module_scope)) {
- return Handle<JSObject>();
+ return MaybeHandle<JSObject>();
}
return module_scope;
@@ -11804,7 +11915,8 @@ class ScopeIterator {
ScopeIterator(Isolate* isolate,
JavaScriptFrame* frame,
- int inlined_jsframe_index)
+ int inlined_jsframe_index,
+ bool ignore_nested_scopes = false)
: isolate_(isolate),
frame_(frame),
inlined_jsframe_index_(inlined_jsframe_index),
@@ -11828,19 +11940,31 @@ class ScopeIterator {
// Return if ensuring debug info failed.
return;
}
- Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
- // Find the break point where execution has stopped.
- BreakLocationIterator break_location_iterator(debug_info,
- ALL_BREAK_LOCATIONS);
- // pc points to the instruction after the current one, possibly a break
- // location as well. So the "- 1" to exclude it from the search.
- break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
- if (break_location_iterator.IsExit()) {
- // We are within the return sequence. At the momemt it is not possible to
+ // Currently it takes too much time to find nested scopes due to script
+ // parsing. Sometimes we want to run the ScopeIterator as fast as possible
+ // (for example, while collecting async call stacks on every
+ // addEventListener call), even if we drop some nested scopes.
+ // Later we may optimize getting the nested scopes (cache the result?)
+ // and include nested scopes into the "fast" iteration case as well.
+ if (!ignore_nested_scopes) {
+ Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
+
+ // Find the break point where execution has stopped.
+ BreakLocationIterator break_location_iterator(debug_info,
+ ALL_BREAK_LOCATIONS);
+ // pc points to the instruction after the current one, possibly a break
+ // location as well. So the "- 1" to exclude it from the search.
+ break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
+
+ // Within the return sequence at the moment it is not possible to
// get a source position which is consistent with the current scope chain.
// Thus all nested with, catch and block contexts are skipped and we only
// provide the function scope.
+ ignore_nested_scopes = break_location_iterator.IsExit();
+ }
+
+ if (ignore_nested_scopes) {
if (scope_info->HasContext()) {
context_ = Handle<Context>(context_->declaration_context(), isolate_);
} else {
@@ -11848,7 +11972,7 @@ class ScopeIterator {
context_ = Handle<Context>(context_->previous(), isolate_);
}
}
- if (scope_info->scope_type() != EVAL_SCOPE) {
+ if (scope_info->scope_type() == FUNCTION_SCOPE) {
nested_scope_chain_.Add(scope_info);
}
} else {
@@ -11976,7 +12100,7 @@ class ScopeIterator {
}
// Return the JavaScript object with the content of the current scope.
- Handle<JSObject> ScopeObject() {
+ MaybeHandle<JSObject> ScopeObject() {
ASSERT(!failed_);
switch (Type()) {
case ScopeIterator::ScopeTypeGlobal:
@@ -12139,16 +12263,12 @@ class ScopeIterator {
};
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
+RUNTIME_FUNCTION(Runtime_GetScopeCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
// Get the frame where the debugging is performed.
@@ -12171,16 +12291,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
// Returns the list of step-in positions (text offset) in a function of the
// stack frame in a range from the current debug break position to the end
// of the corresponding statement.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
+RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
// Get the frame where the debugging is performed.
@@ -12231,9 +12347,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
if (accept) {
if (break_location_iterator.IsStepInLocation(isolate)) {
Smi* position_value = Smi::FromInt(break_location_iterator.position());
- JSObject::SetElement(array, len,
- Handle<Object>(position_value, isolate),
- NONE, kNonStrictMode);
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate,
+ JSObject::SetElement(array, len,
+ Handle<Object>(position_value, isolate),
+ NONE, SLOPPY));
len++;
}
}
@@ -12253,7 +12371,8 @@ static const int kScopeDetailsObjectIndex = 1;
static const int kScopeDetailsSize = 2;
-static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScopeDetails(
+ Isolate* isolate,
ScopeIterator* it) {
// Calculate the size of the result.
int details_size = kScopeDetailsSize;
@@ -12261,11 +12380,12 @@ static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
// Fill in scope details.
details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
- Handle<JSObject> scope_object = it->ScopeObject();
- RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
+ Handle<JSObject> scope_object;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, scope_object, it->ScopeObject(), JSObject);
details->set(kScopeDetailsObjectIndex, *scope_object);
- return *isolate->factory()->NewJSArrayWithElements(details);
+ return isolate->factory()->NewJSArrayWithElements(details);
}
@@ -12278,16 +12398,12 @@ static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
// The array returned contains the following information:
// 0: Scope type
// 1: Scope object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
+RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
@@ -12306,11 +12422,60 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
if (it.Done()) {
return isolate->heap()->undefined_value();
}
- return MaterializeScopeDetails(isolate, &it);
+ Handle<JSObject> details;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, details, MaterializeScopeDetails(isolate, &it));
+ return *details;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
+// Return an array of scope details
+// args[0]: number: break id
+// args[1]: number: frame index
+// args[2]: number: inlined frame index
+// args[3]: boolean: ignore nested scopes
+//
+// The array returned contains arrays with the following information:
+// 0: Scope type
+// 1: Scope object
+RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 3 || args.length() == 4);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
+
+ CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
+ CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
+
+ bool ignore_nested_scopes = false;
+ if (args.length() == 4) {
+ CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
+ ignore_nested_scopes = flag;
+ }
+
+ // Get the frame where the debugging is performed.
+ StackFrame::Id id = UnwrapFrameId(wrapped_id);
+ JavaScriptFrameIterator frame_it(isolate, id);
+ JavaScriptFrame* frame = frame_it.frame();
+
+ List<Handle<JSObject> > result(4);
+ ScopeIterator it(isolate, frame, inlined_jsframe_index, ignore_nested_scopes);
+ for (; !it.Done(); it.Next()) {
+ Handle<JSObject> details;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, details, MaterializeScopeDetails(isolate, &it));
+ result.Add(details);
+ }
+
+ Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
+ for (int i = 0; i < result.length(); ++i) {
+ array->set(i, *result[i]);
+ }
+ return *isolate->factory()->NewJSArrayWithElements(array);
+}
+
+
+RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -12327,7 +12492,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
+RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -12345,7 +12510,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
return isolate->heap()->undefined_value();
}
- return MaterializeScopeDetails(isolate, &it);
+ Handle<JSObject> details;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, details, MaterializeScopeDetails(isolate, &it));
+ return *details;
}
@@ -12371,22 +12539,20 @@ static bool SetScopeVariableValue(ScopeIterator* it, int index,
// args[5]: object: new value
//
// Return true if success and false otherwise
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
+RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
HandleScope scope(isolate);
ASSERT(args.length() == 6);
// Check arguments.
CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
- Handle<Object> new_value = args.at<Object>(5);
+ CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
bool res;
if (args[0]->IsNumber()) {
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
+
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
@@ -12407,7 +12573,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
+RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
@@ -12425,16 +12591,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
+RUNTIME_FUNCTION(Runtime_GetThreadCount) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
-
- // Check arguments.
- Object* result;
- { MaybeObject* maybe_result = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
// Count all archived V8 threads.
int n = 0;
@@ -12461,16 +12622,12 @@ static const int kThreadDetailsSize = 2;
// The array returned contains the following information:
// 0: Is current thread?
// 1: Thread id
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
+RUNTIME_FUNCTION(Runtime_GetThreadDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
// Allocate array for result.
@@ -12511,7 +12668,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
// Sets the disable break state
// args[0]: disable break state
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
+RUNTIME_FUNCTION(Runtime_SetDisableBreak) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
@@ -12525,7 +12682,7 @@ static bool IsPositionAlignmentCodeCorrect(int alignment) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
+RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -12553,17 +12710,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
// args[0]: function
// args[1]: number: break source position (within the function source)
// args[2]: number: break point object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
+RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
- RUNTIME_ASSERT(source_position >= 0);
- Handle<Object> break_point_object_arg = args.at<Object>(2);
+ RUNTIME_ASSERT(source_position >= function->shared()->start_position() &&
+ source_position <= function->shared()->end_position());
+ CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
// Set break point.
- isolate->debug()->SetBreakPoint(function, break_point_object_arg,
- &source_position);
+ RUNTIME_ASSERT(isolate->debug()->SetBreakPoint(
+ function, break_point_object_arg, &source_position));
return Smi::FromInt(source_position);
}
@@ -12576,14 +12734,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
// args[1]: number: break source position (within the script source)
// args[2]: number, breakpoint position alignment
// args[3]: number: break point object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
+RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
RUNTIME_ASSERT(source_position >= 0);
CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
- Handle<Object> break_point_object_arg = args.at<Object>(3);
+ CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
return isolate->ThrowIllegalOperation();
@@ -12599,7 +12757,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
&source_position,
alignment)) {
- return isolate->heap()->undefined_value();
+ return isolate->heap()->undefined_value();
}
return Smi::FromInt(source_position);
@@ -12608,10 +12766,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
// Clear a break point
// args[0]: number: break point object
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
+RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- Handle<Object> break_point_object_arg = args.at<Object>(0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
// Clear break point.
isolate->debug()->ClearBreakPoint(break_point_object_arg);
@@ -12623,16 +12781,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
// Change the state of break on exceptions.
// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
// args[1]: Boolean indicating on/off.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
+RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
- RUNTIME_ASSERT(args[0]->IsNumber());
+ CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
// If the number doesn't match an enum value, the ChangeBreakOnException
// function will default to affecting caught exceptions.
- ExceptionBreakType type =
- static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
+ ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
// Update break point state.
isolate->debug()->ChangeBreakOnException(type, enable);
return isolate->heap()->undefined_value();
@@ -12641,13 +12798,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
// Returns the state of break on exceptions
// args[0]: boolean indicating uncaught exceptions
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
+RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- RUNTIME_ASSERT(args[0]->IsNumber());
+ CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
- ExceptionBreakType type =
- static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
+ ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
bool result = isolate->debug()->IsBreakOnException(type);
return Smi::FromInt(result);
}
@@ -12658,15 +12814,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
// args[1]: step action from the enumeration StepAction
// args[2]: number of times to perform the step, for step out it is the number
// of frames to step down.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
+RUNTIME_FUNCTION(Runtime_PrepareStep) {
HandleScope scope(isolate);
ASSERT(args.length() == 4);
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
+
if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
return isolate->Throw(isolate->heap()->illegal_argument_string());
}
@@ -12713,7 +12866,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
// Clear all stepping set by PrepareStep.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
+RUNTIME_FUNCTION(Runtime_ClearStepping) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
isolate->debug()->ClearStepping();
@@ -12723,59 +12876,58 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
// Helper function to find or create the arguments object for
// Runtime_DebugEvaluate.
-static Handle<JSObject> MaterializeArgumentsObject(
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeArgumentsObject(
Isolate* isolate,
Handle<JSObject> target,
Handle<JSFunction> function) {
// Do not materialize the arguments object for eval or top-level code.
// Skip if "arguments" is already taken.
if (!function->shared()->is_function() ||
- JSReceiver::HasLocalProperty(target,
- isolate->factory()->arguments_string())) {
+ JSReceiver::HasOwnProperty(
+ target, isolate->factory()->arguments_string())) {
return target;
}
// FunctionGetArguments can't throw an exception.
Handle<JSObject> arguments = Handle<JSObject>::cast(
Accessors::FunctionGetArguments(function));
- Runtime::SetObjectProperty(isolate, target,
- isolate->factory()->arguments_string(),
- arguments,
- ::NONE,
- kNonStrictMode);
+ Handle<String> arguments_str = isolate->factory()->arguments_string();
+ RETURN_ON_EXCEPTION(
+ isolate,
+ Runtime::SetObjectProperty(
+ isolate, target, arguments_str, arguments, ::NONE, SLOPPY),
+ JSObject);
return target;
}
// Compile and evaluate source for the given context.
-static MaybeObject* DebugEvaluate(Isolate* isolate,
- Handle<Context> context,
- Handle<Object> context_extension,
- Handle<Object> receiver,
- Handle<String> source) {
+static MaybeHandle<Object> DebugEvaluate(Isolate* isolate,
+ Handle<Context> context,
+ Handle<Object> context_extension,
+ Handle<Object> receiver,
+ Handle<String> source) {
if (context_extension->IsJSObject()) {
Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
Handle<JSFunction> closure(context->closure(), isolate);
context = isolate->factory()->NewWithContext(closure, context, extension);
}
- Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
- source,
- context,
- context->IsNativeContext(),
- CLASSIC_MODE,
- NO_PARSE_RESTRICTION,
- RelocInfo::kNoPosition);
- RETURN_IF_EMPTY_HANDLE(isolate, shared);
-
- Handle<JSFunction> eval_fun =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(
- shared, context, NOT_TENURED);
- bool pending_exception;
- Handle<Object> result = Execution::Call(
- isolate, eval_fun, receiver, 0, NULL, &pending_exception);
+ Handle<JSFunction> eval_fun;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, eval_fun,
+ Compiler::GetFunctionFromEval(source,
+ context,
+ SLOPPY,
+ NO_PARSE_RESTRICTION,
+ RelocInfo::kNoPosition),
+ Object);
- if (pending_exception) return Failure::Exception();
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result,
+ Execution::Call(isolate, eval_fun, receiver, 0, NULL),
+ Object);
// Skip the global proxy as it has no properties and always delegates to the
// real global object.
@@ -12785,7 +12937,7 @@ static MaybeObject* DebugEvaluate(Isolate* isolate,
// Clear the oneshot breakpoints so that the debugger does not step further.
isolate->debug()->ClearStepping();
- return *result;
+ return result;
}
@@ -12794,25 +12946,23 @@ static MaybeObject* DebugEvaluate(Isolate* isolate,
// - Parameters and stack-allocated locals need to be materialized. Altered
// values need to be written back to the stack afterwards.
// - The arguments object needs to materialized.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
+RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
HandleScope scope(isolate);
// Check the execution state and decode arguments frame and source to be
// evaluated.
ASSERT(args.length() == 6);
- Object* check_result;
- { MaybeObject* maybe_result = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_result->ToObject(&check_result)) return maybe_result;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
+
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
- Handle<Object> context_extension(args[5], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 5);
// Handle the processing of break.
- DisableBreak disable_break_save(isolate, disable_break);
+ DisableBreak disable_break_scope(isolate->debug(), disable_break);
// Get the frame where the debugging is performed.
StackFrame::Id id = UnwrapFrameId(wrapped_id);
@@ -12836,24 +12986,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
Handle<JSObject> materialized =
isolate->factory()->NewJSObject(isolate->object_function());
- materialized = MaterializeStackLocalsWithFrameInspector(
- isolate, materialized, function, &frame_inspector);
- RETURN_IF_EMPTY_HANDLE(isolate, materialized);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, materialized,
+ MaterializeStackLocalsWithFrameInspector(
+ isolate, materialized, function, &frame_inspector));
- materialized = MaterializeArgumentsObject(isolate, materialized, function);
- RETURN_IF_EMPTY_HANDLE(isolate, materialized);
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, materialized,
+ MaterializeArgumentsObject(isolate, materialized, function));
// Add the materialized object in a with-scope to shadow the stack locals.
context = isolate->factory()->NewWithContext(function, context, materialized);
Handle<Object> receiver(frame->receiver(), isolate);
- Object* evaluate_result_object;
- { MaybeObject* maybe_result =
- DebugEvaluate(isolate, context, context_extension, receiver, source);
- if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
- }
-
- Handle<Object> result(evaluate_result_object, isolate);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ DebugEvaluate(isolate, context, context_extension, receiver, source));
// Write back potential changes to materialized stack locals to the stack.
UpdateStackLocalsFromMaterializedObject(
@@ -12863,23 +13012,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
+RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
HandleScope scope(isolate);
// Check the execution state and decode arguments frame and source to be
// evaluated.
ASSERT(args.length() == 4);
- Object* check_result;
- { MaybeObject* maybe_result = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_result->ToObject(&check_result)) return maybe_result;
- }
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
+
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
- Handle<Object> context_extension(args[3], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 3);
// Handle the processing of break.
- DisableBreak disable_break_save(isolate, disable_break);
+ DisableBreak disable_break_scope(isolate->debug(), disable_break);
// Enter the top context from before the debugger was invoked.
SaveContext save(isolate);
@@ -12895,11 +13042,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
// debugger was invoked.
Handle<Context> context = isolate->native_context();
Handle<Object> receiver = isolate->global_object();
- return DebugEvaluate(isolate, context, context_extension, receiver, source);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ DebugEvaluate(isolate, context, context_extension, receiver, source));
+ return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
+RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
@@ -12914,14 +13065,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
// instances->set(i, *GetScriptWrapper(script))
// is unsafe as GetScriptWrapper might call GC and the C++ compiler might
// already have dereferenced the instances handle.
- Handle<JSValue> wrapper = GetScriptWrapper(script);
+ Handle<JSObject> wrapper = Script::GetWrapper(script);
instances->set(i, *wrapper);
}
// Return result as a JS array.
Handle<JSObject> result =
isolate->factory()->NewJSObject(isolate->array_function());
- isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
+ JSArray::SetContent(Handle<JSArray>::cast(result), instances);
return *result;
}
@@ -13001,21 +13152,13 @@ static int DebugReferencedBy(HeapIterator* iterator,
// args[0]: the object to find references to
// args[1]: constructor function for instances to exclude (Mirror)
// args[2]: the the maximum number of objects to return
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
- // First perform a full GC in order to avoid references from dead objects.
- isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
- "%DebugReferencedBy");
- // The heap iterator reserves the right to do a GC to make the heap iterable.
- // Due to the GC above we know it won't need to do that, but it seems cleaner
- // to get the heap iterator constructed before we start having unprotected
- // Object* locals that are not protected by handles.
-
// Check parameters.
- CONVERT_ARG_CHECKED(JSObject, target, 0);
- Object* instance_filter = args[1];
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1);
RUNTIME_ASSERT(instance_filter->IsUndefined() ||
instance_filter->IsJSObject());
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
@@ -13023,40 +13166,42 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
// Get the constructor function for context extension and arguments array.
- JSObject* arguments_boilerplate =
- isolate->context()->native_context()->arguments_boilerplate();
- JSFunction* arguments_function =
- JSFunction::cast(arguments_boilerplate->map()->constructor());
+ Handle<JSObject> arguments_boilerplate(
+ isolate->context()->native_context()->sloppy_arguments_boilerplate());
+ Handle<JSFunction> arguments_function(
+ JSFunction::cast(arguments_boilerplate->map()->constructor()));
// Get the number of referencing objects.
int count;
+ // First perform a full GC in order to avoid dead objects and to make the heap
+ // iterable.
Heap* heap = isolate->heap();
- HeapIterator heap_iterator(heap);
- count = DebugReferencedBy(&heap_iterator,
- target, instance_filter, max_references,
- NULL, 0, arguments_function);
+ heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
+ {
+ HeapIterator heap_iterator(heap);
+ count = DebugReferencedBy(&heap_iterator,
+ *target, *instance_filter, max_references,
+ NULL, 0, *arguments_function);
+ }
// Allocate an array to hold the result.
- Object* object;
- { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- FixedArray* instances = FixedArray::cast(object);
+ Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
// Fill the referencing objects.
- // AllocateFixedArray above does not make the heap non-iterable.
- ASSERT(heap->IsHeapIterable());
- HeapIterator heap_iterator2(heap);
- count = DebugReferencedBy(&heap_iterator2,
- target, instance_filter, max_references,
- instances, count, arguments_function);
+ {
+ HeapIterator heap_iterator(heap);
+ count = DebugReferencedBy(&heap_iterator,
+ *target, *instance_filter, max_references,
+ *instances, count, *arguments_function);
+ }
// Return result as JS array.
- Object* result;
- MaybeObject* maybe_result = heap->AllocateJSObject(
+ Handle<JSFunction> constructor(
isolate->context()->native_context()->array_function());
- if (!maybe_result->ToObject(&result)) return maybe_result;
- return JSArray::cast(result)->SetContent(instances);
+
+ Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
+ JSArray::SetContent(Handle<JSArray>::cast(result), instances);
+ return *result;
}
@@ -13095,66 +13240,65 @@ static int DebugConstructedBy(HeapIterator* iterator,
// Scan the heap for objects constructed by a specific function.
// args[0]: the constructor to find instances of
// args[1]: the the maximum number of objects to return
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
- // First perform a full GC in order to avoid dead objects.
- Heap* heap = isolate->heap();
- heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
// Check parameters.
- CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
RUNTIME_ASSERT(max_references >= 0);
// Get the number of referencing objects.
int count;
- HeapIterator heap_iterator(heap);
- count = DebugConstructedBy(&heap_iterator,
- constructor,
- max_references,
- NULL,
- 0);
+ // First perform a full GC in order to avoid dead objects and to make the heap
+ // iterable.
+ Heap* heap = isolate->heap();
+ heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
+ {
+ HeapIterator heap_iterator(heap);
+ count = DebugConstructedBy(&heap_iterator,
+ *constructor,
+ max_references,
+ NULL,
+ 0);
+ }
// Allocate an array to hold the result.
- Object* object;
- { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- FixedArray* instances = FixedArray::cast(object);
+ Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
- ASSERT(isolate->heap()->IsHeapIterable());
// Fill the referencing objects.
- HeapIterator heap_iterator2(heap);
- count = DebugConstructedBy(&heap_iterator2,
- constructor,
- max_references,
- instances,
- count);
+ {
+ HeapIterator heap_iterator2(heap);
+ count = DebugConstructedBy(&heap_iterator2,
+ *constructor,
+ max_references,
+ *instances,
+ count);
+ }
// Return result as JS array.
- Object* result;
- { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
+ Handle<JSFunction> array_function(
isolate->context()->native_context()->array_function());
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- return JSArray::cast(result)->SetContent(instances);
+ Handle<JSObject> result = isolate->factory()->NewJSObject(array_function);
+ JSArray::SetContent(Handle<JSArray>::cast(result), instances);
+ return *result;
}
// Find the effective prototype object as returned by __proto__.
// args[0]: the object to find the prototype for.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
+ HandleScope shs(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(JSObject, obj, 0);
- return GetPrototypeSkipHiddenPrototypes(isolate, obj);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
+ return *GetPrototypeSkipHiddenPrototypes(isolate, obj);
}
// Patches script source (should be called upon BeforeCompile event).
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
+RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -13172,7 +13316,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
+RUNTIME_FUNCTION(Runtime_SystemBreak) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
OS::DebugBreak();
@@ -13180,14 +13324,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
+RUNTIME_FUNCTION(Runtime_DebugDisassembleFunction) {
HandleScope scope(isolate);
#ifdef DEBUG
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
- if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
- return Failure::Exception();
+ if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
+ return isolate->heap()->exception();
}
func->code()->PrintLn();
#endif // DEBUG
@@ -13195,14 +13339,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
+RUNTIME_FUNCTION(Runtime_DebugDisassembleConstructor) {
HandleScope scope(isolate);
#ifdef DEBUG
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
- if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
- return Failure::Exception();
+ if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
+ return isolate->heap()->exception();
}
func->shared()->construct_stub()->PrintLn();
#endif // DEBUG
@@ -13210,7 +13354,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
+RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -13248,10 +13392,9 @@ static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
// For a script finds all SharedFunctionInfo's in the heap that points
// to this script. Returns JSArray of SharedFunctionInfo wrapped
// in OpaqueReferences.
-RUNTIME_FUNCTION(MaybeObject*,
- Runtime_LiveEditFindSharedFunctionInfosForScript) {
+RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSValue, script_value, 0);
@@ -13265,8 +13408,6 @@ RUNTIME_FUNCTION(MaybeObject*,
int number;
Heap* heap = isolate->heap();
{
- heap->EnsureHeapIsIterable();
- DisallowHeapAllocation no_allocation;
HeapIterator heap_iterator(heap);
Script* scr = *script;
FixedArray* arr = *array;
@@ -13274,8 +13415,6 @@ RUNTIME_FUNCTION(MaybeObject*,
}
if (number > kBufferSize) {
array = isolate->factory()->NewFixedArray(number);
- heap->EnsureHeapIsIterable();
- DisallowHeapAllocation no_allocation;
HeapIterator heap_iterator(heap);
Script* scr = *script;
FixedArray* arr = *array;
@@ -13298,9 +13437,9 @@ RUNTIME_FUNCTION(MaybeObject*,
// Returns a JSArray of compilation infos. The array is ordered so that
// each function with all its descendant is always stored in a continues range
// with the function itself going first. The root function is a script function.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
+RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(JSValue, script, 0);
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
@@ -13308,71 +13447,72 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
RUNTIME_ASSERT(script->value()->IsScript());
Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
- JSArray* result = LiveEdit::GatherCompileInfo(script_handle, source);
-
- if (isolate->has_pending_exception()) {
- return Failure::Exception();
- }
-
- return result;
+ Handle<JSArray> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, LiveEdit::GatherCompileInfo(script_handle, source));
+ return *result;
}
// Changes the source of the script to a new_source.
// If old_script_name is provided (i.e. is a String), also creates a copy of
// the script with its original source and sends notification to debugger.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
+RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
- Handle<Object> old_script_name(args[2], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2);
RUNTIME_ASSERT(original_script_value->value()->IsScript());
Handle<Script> original_script(Script::cast(original_script_value->value()));
- Object* old_script = LiveEdit::ChangeScriptSource(original_script,
- new_source,
- old_script_name);
+ Handle<Object> old_script = LiveEdit::ChangeScriptSource(
+ original_script, new_source, old_script_name);
if (old_script->IsScript()) {
- Handle<Script> script_handle(Script::cast(old_script));
- return *(GetScriptWrapper(script_handle));
+ Handle<Script> script_handle = Handle<Script>::cast(old_script);
+ return *Script::GetWrapper(script_handle);
} else {
return isolate->heap()->null_value();
}
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
+RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
- return LiveEdit::FunctionSourceUpdated(shared_info);
+ RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
+
+ LiveEdit::FunctionSourceUpdated(shared_info);
+ return isolate->heap()->undefined_value();
}
// Replaces code of SharedFunctionInfo with a new one.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
+RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
+ RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
- return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
+ LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
+ return isolate->heap()->undefined_value();
}
// Connects SharedFunctionInfo to another script.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
+RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 2);
- Handle<Object> function_object(args[0], isolate);
- Handle<Object> script_object(args[1], isolate);
+ CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1);
if (function_object->IsJSValue()) {
Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
@@ -13381,7 +13521,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
Script* script = Script::cast(JSValue::cast(*script_object)->value());
script_object = Handle<Object>(script, isolate);
}
-
+ RUNTIME_ASSERT(function_wrapper->value()->IsSharedFunctionInfo());
LiveEdit::SetFunctionScript(function_wrapper, script_object);
} else {
// Just ignore this. We may not have a SharedFunctionInfo for some functions
@@ -13394,18 +13534,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
// In a code of a parent function replaces original function as embedded object
// with a substitution one.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
+RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
+ RUNTIME_ASSERT(parent_wrapper->value()->IsSharedFunctionInfo());
+ RUNTIME_ASSERT(orig_wrapper->value()->IsSharedFunctionInfo());
+ RUNTIME_ASSERT(subst_wrapper->value()->IsSharedFunctionInfo());
- LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
- subst_wrapper);
-
+ LiveEdit::ReplaceRefToNestedFunction(
+ parent_wrapper, orig_wrapper, subst_wrapper);
return isolate->heap()->undefined_value();
}
@@ -13415,14 +13557,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
// array of groups of 3 numbers:
// (change_begin, change_end, change_end_new_position).
// Each group describes a change in text; groups are sorted by change_begin.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
+RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
+ RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_array))
- return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
+ LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
+ return isolate->heap()->undefined_value();
}
@@ -13430,12 +13574,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
// checks that none of them have activations on stacks (of any thread).
// Returns array of the same length with corresponding results of
// LiveEdit::FunctionPatchabilityStatus type.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
+RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
+ RUNTIME_ASSERT(shared_array->length()->IsSmi());
+ int array_length = Smi::cast(shared_array->length())->value();
+ for (int i = 0; i < array_length; i++) {
+ Handle<Object> element =
+ Object::GetElement(isolate, shared_array, i).ToHandleChecked();
+ RUNTIME_ASSERT(
+ element->IsJSValue() &&
+ Handle<JSValue>::cast(element)->value()->IsSharedFunctionInfo());
+ }
return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
}
@@ -13444,9 +13597,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
// Compares 2 strings line-by-line, then token-wise and returns diff in form
// of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
// of diff chunks.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
+RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
@@ -13457,17 +13610,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
// Restarts a call frame and completely drops all frames above.
// Returns true if successful. Otherwise returns undefined or an error message.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
+RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
- // Check arguments.
- Object* check;
- { MaybeObject* maybe_check = Runtime_CheckExecutionState(
- RUNTIME_ARGUMENTS(isolate, args));
- if (!maybe_check->ToObject(&check)) return maybe_check;
- }
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
Heap* heap = isolate->heap();
@@ -13496,9 +13645,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
// A testing entry. Returns statement position which is the closest to
// source_position.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
+RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
HandleScope scope(isolate);
- CHECK(isolate->debugger()->live_edit_enabled());
+ CHECK(isolate->debug()->live_edit_enabled());
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
@@ -13534,63 +13683,59 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
// Calls specified function with or without entering the debugger.
// This is used in unit tests to run code as if debugger is entered or simply
// to have a stack with C++ frame in the middle.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
+RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
- Handle<Object> result;
- bool pending_exception;
- {
- if (without_debugger) {
- result = Execution::Call(isolate,
- function,
- isolate->global_object(),
- 0,
- NULL,
- &pending_exception);
- } else {
- EnterDebugger enter_debugger(isolate);
- result = Execution::Call(isolate,
- function,
- isolate->global_object(),
- 0,
- NULL,
- &pending_exception);
- }
- }
- if (!pending_exception) {
- return *result;
+ MaybeHandle<Object> maybe_result;
+ if (without_debugger) {
+ maybe_result = Execution::Call(isolate,
+ function,
+ isolate->global_object(),
+ 0,
+ NULL);
} else {
- return Failure::Exception();
+ DebugScope debug_scope(isolate->debug());
+ maybe_result = Execution::Call(isolate,
+ function,
+ isolate->global_object(),
+ 0,
+ NULL);
}
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result);
+ return *result;
}
// Sets a v8 flag.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
+RUNTIME_FUNCTION(Runtime_SetFlags) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(String, arg, 0);
SmartArrayPointer<char> flags =
arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- FlagList::SetFlagsFromString(*flags, StrLength(*flags));
+ FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
return isolate->heap()->undefined_value();
}
// Performs a GC.
// Presently, it only does a full GC.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
+RUNTIME_FUNCTION(Runtime_CollectGarbage) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
return isolate->heap()->undefined_value();
}
// Gets the current heap usage.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
+RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 0);
int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
if (!Smi::IsValid(usage)) {
return *isolate->factory()->NewNumberFromInt(usage);
@@ -13598,12 +13743,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
return Smi::FromInt(usage);
}
-#endif // ENABLE_DEBUGGER_SUPPORT
-
#ifdef V8_I18N_SUPPORT
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
+RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
HandleScope scope(isolate);
+ Factory* factory = isolate->factory();
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
@@ -13620,7 +13764,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &error);
if (U_FAILURE(error) || icu_length == 0) {
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
+ return *factory->NewStringFromAsciiChecked(kInvalidTag);
}
char result[ULOC_FULLNAME_CAPACITY];
@@ -13629,15 +13773,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
if (U_FAILURE(error)) {
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
+ return *factory->NewStringFromAsciiChecked(kInvalidTag);
}
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
+ return *factory->NewStringFromAsciiChecked(result);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
+RUNTIME_FUNCTION(Runtime_AvailableLocalesOf) {
HandleScope scope(isolate);
+ Factory* factory = isolate->factory();
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
@@ -13658,7 +13803,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
UErrorCode error = U_ZERO_ERROR;
char result[ULOC_FULLNAME_CAPACITY];
Handle<JSObject> locales =
- isolate->factory()->NewJSObject(isolate->object_function());
+ factory->NewJSObject(isolate->object_function());
for (int32_t i = 0; i < count; ++i) {
const char* icu_name = available_locales[i].getName();
@@ -13671,11 +13816,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
continue;
}
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(
locales,
- isolate->factory()->NewStringFromAscii(CStrVector(result)),
- isolate->factory()->NewNumber(i),
+ factory->NewStringFromAsciiChecked(result),
+ factory->NewNumber(i),
NONE));
}
@@ -13683,8 +13828,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
+ HandleScope scope(isolate);
+ Factory* factory = isolate->factory();
ASSERT(args.length() == 0);
@@ -13696,35 +13842,38 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
uloc_toLanguageTag(
default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
if (U_SUCCESS(status)) {
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
+ return *factory->NewStringFromAsciiChecked(result);
}
- return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
+ return *factory->NewStringFromStaticAscii("und");
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
+RUNTIME_FUNCTION(Runtime_GetLanguageTagVariants) {
HandleScope scope(isolate);
+ Factory* factory = isolate->factory();
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
uint32_t length = static_cast<uint32_t>(input->length()->Number());
- Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
- Handle<Name> maximized =
- isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
- Handle<Name> base =
- isolate->factory()->NewStringFromAscii(CStrVector("base"));
+ // Set some limit to prevent fuzz tests from going OOM.
+ // Can be bumped when callers' requirements change.
+ RUNTIME_ASSERT(length < 100);
+ Handle<FixedArray> output = factory->NewFixedArray(length);
+ Handle<Name> maximized = factory->NewStringFromStaticAscii("maximized");
+ Handle<Name> base = factory->NewStringFromStaticAscii("base");
for (unsigned int i = 0; i < length; ++i) {
- MaybeObject* maybe_string = input->GetElement(isolate, i);
- Object* locale_id;
- if (!maybe_string->ToObject(&locale_id) || !locale_id->IsString()) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
+ Handle<Object> locale_id;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, locale_id, Object::GetElement(isolate, input, i));
+ if (!locale_id->IsString()) {
+ return isolate->Throw(*factory->illegal_argument_string());
}
v8::String::Utf8Value utf8_locale_id(
- v8::Utils::ToLocal(Handle<String>(String::cast(locale_id))));
+ v8::Utils::ToLocal(Handle<String>::cast(locale_id)));
UErrorCode error = U_ZERO_ERROR;
@@ -13735,7 +13884,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
&icu_locale_length, &error);
if (U_FAILURE(error) || icu_locale_length == 0) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
+ return isolate->Throw(*factory->illegal_argument_string());
}
// Maximize the locale.
@@ -13768,33 +13917,113 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
if (U_FAILURE(error)) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
+ return isolate->Throw(*factory->illegal_argument_string());
}
- Handle<JSObject> result =
- isolate->factory()->NewJSObject(isolate->object_function());
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(
result,
maximized,
- isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
+ factory->NewStringFromAsciiChecked(base_max_locale),
NONE));
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(
result,
base,
- isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
+ factory->NewStringFromAsciiChecked(base_locale),
NONE));
output->set(i, *result);
}
- Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
+ Handle<JSArray> result = factory->NewJSArrayWithElements(output);
result->set_length(Smi::FromInt(length));
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
+RUNTIME_FUNCTION(Runtime_IsInitializedIntlObject) {
+ HandleScope scope(isolate);
+
+ ASSERT(args.length() == 1);
+
+ CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
+
+ if (!input->IsJSObject()) return isolate->heap()->false_value();
+ Handle<JSObject> obj = Handle<JSObject>::cast(input);
+
+ Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
+ Handle<Object> tag(obj->GetHiddenProperty(marker), isolate);
+ return isolate->heap()->ToBoolean(!tag->IsTheHole());
+}
+
+
+RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType) {
+ HandleScope scope(isolate);
+
+ ASSERT(args.length() == 2);
+
+ CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, expected_type, 1);
+
+ if (!input->IsJSObject()) return isolate->heap()->false_value();
+ Handle<JSObject> obj = Handle<JSObject>::cast(input);
+
+ Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
+ Handle<Object> tag(obj->GetHiddenProperty(marker), isolate);
+ return isolate->heap()->ToBoolean(
+ tag->IsString() && String::cast(*tag)->Equals(*expected_type));
+}
+
+
+RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
+ HandleScope scope(isolate);
+
+ ASSERT(args.length() == 3);
+
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, input, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, impl, 2);
+
+ Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
+ JSObject::SetHiddenProperty(input, marker, type);
+
+ marker = isolate->factory()->intl_impl_object_string();
+ JSObject::SetHiddenProperty(input, marker, impl);
+
+ return isolate->heap()->undefined_value();
+}
+
+
+RUNTIME_FUNCTION(Runtime_GetImplFromInitializedIntlObject) {
+ HandleScope scope(isolate);
+
+ ASSERT(args.length() == 1);
+
+ CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
+
+ if (!input->IsJSObject()) {
+ Vector< Handle<Object> > arguments = HandleVector(&input, 1);
+ Handle<Object> type_error =
+ isolate->factory()->NewTypeError("not_intl_object", arguments);
+ return isolate->Throw(*type_error);
+ }
+
+ Handle<JSObject> obj = Handle<JSObject>::cast(input);
+
+ Handle<String> marker = isolate->factory()->intl_impl_object_string();
+ Handle<Object> impl(obj->GetHiddenProperty(marker), isolate);
+ if (impl->IsTheHole()) {
+ Vector< Handle<Object> > arguments = HandleVector(&obj, 1);
+ Handle<Object> type_error =
+ isolate->factory()->NewTypeError("not_intl_object", arguments);
+ return isolate->Throw(*type_error);
+ }
+ return *impl;
+}
+
+
+RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -13807,13 +14036,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
I18N::GetTemplate(isolate);
// Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- date_format_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<JSObject> local_object;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, local_object,
+ Execution::InstantiateObject(date_format_template));
// Set date time formatter as internal field of the resulting JS object.
icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
@@ -13823,23 +14049,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(
local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
+ isolate->factory()->NewStringFromStaticAscii("dateFormat"),
+ isolate->factory()->NewStringFromStaticAscii("valid"),
NONE));
// Make object handle weak so we can delete the data format once GC kicks in.
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
- GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
- NULL,
+ GlobalHandles::MakeWeak(wrapper.location(),
+ reinterpret_cast<void*>(wrapper.location()),
DateFormat::DeleteDateFormat);
return *local_object;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
+RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -13847,13 +14073,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
- bool has_pending_exception = false;
- Handle<Object> value =
- Execution::ToNumber(isolate, date, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<Object> value;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, value, Execution::ToNumber(isolate, date));
icu::SimpleDateFormat* date_format =
DateFormat::UnpackDateFormat(isolate, date_format_holder);
@@ -13862,14 +14084,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
icu::UnicodeString result;
date_format->format(value->Number(), result);
- return *isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(result.getBuffer()),
- result.length()));
+ Handle<String> result_str;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result_str,
+ isolate->factory()->NewStringFromTwoByte(
+ Vector<const uint16_t>(
+ reinterpret_cast<const uint16_t*>(result.getBuffer()),
+ result.length())));
+ return *result_str;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
+RUNTIME_FUNCTION(Runtime_InternalDateParse) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -13887,19 +14113,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
UDate date = date_format->parse(u_date, status);
if (U_FAILURE(status)) return isolate->heap()->undefined_value();
- bool has_pending_exception = false;
- Handle<JSDate> result = Handle<JSDate>::cast(
- Execution::NewDate(
- isolate, static_cast<double>(date), &has_pending_exception));
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Execution::NewDate(isolate, static_cast<double>(date)));
+ ASSERT(result->IsJSDate());
return *result;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
+RUNTIME_FUNCTION(Runtime_CreateNumberFormat) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -13912,13 +14135,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
I18N::GetTemplate(isolate);
// Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- number_format_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<JSObject> local_object;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, local_object,
+ Execution::InstantiateObject(number_format_template));
// Set number formatter as internal field of the resulting JS object.
icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
@@ -13928,22 +14148,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(
local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
+ isolate->factory()->NewStringFromStaticAscii("numberFormat"),
+ isolate->factory()->NewStringFromStaticAscii("valid"),
NONE));
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
- GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
- NULL,
+ GlobalHandles::MakeWeak(wrapper.location(),
+ reinterpret_cast<void*>(wrapper.location()),
NumberFormat::DeleteNumberFormat);
return *local_object;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
+RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -13951,13 +14171,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
- bool has_pending_exception = false;
- Handle<Object> value = Execution::ToNumber(
- isolate, number, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<Object> value;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, value, Execution::ToNumber(isolate, number));
icu::DecimalFormat* number_format =
NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
@@ -13966,14 +14182,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
icu::UnicodeString result;
number_format->format(value->Number(), result);
- return *isolate->factory()->NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(result.getBuffer()),
- result.length()));
+ Handle<String> result_str;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result_str,
+ isolate->factory()->NewStringFromTwoByte(
+ Vector<const uint16_t>(
+ reinterpret_cast<const uint16_t*>(result.getBuffer()),
+ result.length())));
+ return *result_str;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
+RUNTIME_FUNCTION(Runtime_InternalNumberParse) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -14012,7 +14232,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
+RUNTIME_FUNCTION(Runtime_CreateCollator) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -14024,13 +14244,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
// Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- collator_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<JSObject> local_object;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, local_object, Execution::InstantiateObject(collator_template));
// Set collator as internal field of the resulting JS object.
icu::Collator* collator = Collator::InitializeCollator(
@@ -14040,22 +14256,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(
local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("collator")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
+ isolate->factory()->NewStringFromStaticAscii("collator"),
+ isolate->factory()->NewStringFromStaticAscii("valid"),
NONE));
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
- GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
- NULL,
+ GlobalHandles::MakeWeak(wrapper.location(),
+ reinterpret_cast<void*>(wrapper.location()),
Collator::DeleteCollator);
return *local_object;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
+RUNTIME_FUNCTION(Runtime_InternalCompare) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -14083,7 +14299,42 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) {
+RUNTIME_FUNCTION(Runtime_StringNormalize) {
+ HandleScope scope(isolate);
+ static const UNormalizationMode normalizationForms[] =
+ { UNORM_NFC, UNORM_NFD, UNORM_NFKC, UNORM_NFKD };
+
+ ASSERT(args.length() == 2);
+
+ CONVERT_ARG_HANDLE_CHECKED(String, stringValue, 0);
+ CONVERT_NUMBER_CHECKED(int, form_id, Int32, args[1]);
+ RUNTIME_ASSERT(form_id >= 0 &&
+ static_cast<size_t>(form_id) < ARRAY_SIZE(normalizationForms));
+
+ v8::String::Value string_value(v8::Utils::ToLocal(stringValue));
+ const UChar* u_value = reinterpret_cast<const UChar*>(*string_value);
+
+ // TODO(mnita): check Normalizer2 (not available in ICU 46)
+ UErrorCode status = U_ZERO_ERROR;
+ icu::UnicodeString result;
+ icu::Normalizer::normalize(u_value, normalizationForms[form_id], 0,
+ result, status);
+ if (U_FAILURE(status)) {
+ return isolate->heap()->undefined_value();
+ }
+
+ Handle<String> result_str;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result_str,
+ isolate->factory()->NewStringFromTwoByte(
+ Vector<const uint16_t>(
+ reinterpret_cast<const uint16_t*>(result.getBuffer()),
+ result.length())));
+ return *result_str;
+}
+
+
+RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
@@ -14096,13 +14347,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) {
I18N::GetTemplate2(isolate);
// Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- break_iterator_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<JSObject> local_object;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, local_object,
+ Execution::InstantiateObject(break_iterator_template));
// Set break iterator as internal field of the resulting JS object.
icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
@@ -14114,24 +14362,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) {
// Make sure that the pointer to adopted text is NULL.
local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
- RETURN_IF_EMPTY_HANDLE(isolate,
- JSObject::SetLocalPropertyIgnoreAttributes(
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSObject::SetOwnPropertyIgnoreAttributes(
local_object,
- isolate->factory()->NewStringFromAscii(CStrVector("breakIterator")),
- isolate->factory()->NewStringFromAscii(CStrVector("valid")),
+ isolate->factory()->NewStringFromStaticAscii("breakIterator"),
+ isolate->factory()->NewStringFromStaticAscii("valid"),
NONE));
// Make object handle weak so we can delete the break iterator once GC kicks
// in.
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
- GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
- NULL,
+ GlobalHandles::MakeWeak(wrapper.location(),
+ reinterpret_cast<void*>(wrapper.location()),
BreakIterator::DeleteBreakIterator);
return *local_object;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorAdoptText) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -14158,7 +14406,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorAdoptText) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorFirst) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorFirst) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14173,7 +14421,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorFirst) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorNext) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorNext) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14188,7 +14436,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorNext) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorCurrent) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14203,7 +14451,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorCurrent) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorBreakType) {
+RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14220,17 +14468,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorBreakType) {
int32_t status = rule_based_iterator->getRuleStatus();
// Keep return values in sync with JavaScript BreakType enum.
if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("none"));
+ return *isolate->factory()->NewStringFromStaticAscii("none");
} else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("number"));
+ return *isolate->factory()->NewStringFromStaticAscii("number");
} else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("letter"));
+ return *isolate->factory()->NewStringFromStaticAscii("letter");
} else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("kana"));
+ return *isolate->factory()->NewStringFromStaticAscii("kana");
} else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
- return *isolate->factory()->NewStringFromAscii(CStrVector("ideo"));
+ return *isolate->factory()->NewStringFromStaticAscii("ideo");
} else {
- return *isolate->factory()->NewStringFromAscii(CStrVector("unknown"));
+ return *isolate->factory()->NewStringFromStaticAscii("unknown");
}
}
#endif // V8_I18N_SUPPORT
@@ -14249,8 +14497,6 @@ static Handle<Object> Runtime_GetScriptFromScriptName(
Handle<Script> script;
Factory* factory = script_name->GetIsolate()->factory();
Heap* heap = script_name->GetHeap();
- heap->EnsureHeapIsIterable();
- DisallowHeapAllocation no_allocation_during_heap_iteration;
HeapIterator iterator(heap);
HeapObject* obj = NULL;
while (script.is_null() && ((obj = iterator.next()) != NULL)) {
@@ -14268,14 +14514,14 @@ static Handle<Object> Runtime_GetScriptFromScriptName(
if (script.is_null()) return factory->undefined_value();
// Return the script found.
- return GetScriptWrapper(script);
+ return Script::GetWrapper(script);
}
// Get the script object from script data. NOTE: Regarding performance
// see the NOTE for GetScriptFromScriptData.
// args[0]: script data for the script to find the source for
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
+RUNTIME_FUNCTION(Runtime_GetScript) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -14292,11 +14538,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
// Collect the raw data for a stack trace. Returns an array of 4
// element segments each containing a receiver, function, code and
// native code offset.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
+RUNTIME_FUNCTION(Runtime_CollectStackTrace) {
HandleScope scope(isolate);
- ASSERT_EQ(args.length(), 3);
+ ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
- Handle<Object> caller = args.at<Object>(1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, caller, 1);
CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
// Optionally capture a more detailed stack trace for the message.
@@ -14308,12 +14554,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
// Retrieve the stack trace. This is the raw stack trace that yet has to
// be formatted. Since we only need this once, clear it afterwards.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
+RUNTIME_FUNCTION(Runtime_GetAndClearOverflowedStackTrace) {
HandleScope scope(isolate);
- ASSERT_EQ(args.length(), 1);
+ ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
Handle<String> key = isolate->factory()->hidden_stack_trace_string();
- Handle<Object> result(error_object->GetHiddenProperty(*key), isolate);
+ Handle<Object> result(error_object->GetHiddenProperty(key), isolate);
if (result->IsTheHole()) return isolate->heap()->undefined_value();
RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
JSObject::DeleteHiddenProperty(error_object, key);
@@ -14322,22 +14568,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
// Returns V8 version as a string.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
- SealHandleScope shs(isolate);
- ASSERT_EQ(args.length(), 0);
+RUNTIME_FUNCTION(Runtime_GetV8Version) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 0);
const char* version_string = v8::V8::GetVersion();
- return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string),
- NOT_TENURED);
+ return *isolate->factory()->NewStringFromAsciiChecked(version_string);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
+RUNTIME_FUNCTION(Runtime_Abort) {
SealHandleScope shs(isolate);
- ASSERT(args.length() == 2);
- OS::PrintError("abort: %s\n",
- reinterpret_cast<char*>(args[0]) + args.smi_at(1));
+ ASSERT(args.length() == 1);
+ CONVERT_SMI_ARG_CHECKED(message_id, 0);
+ const char* message = GetBailoutReason(
+ static_cast<BailoutReason>(message_id));
+ OS::PrintError("abort: %s\n", message);
isolate->PrintStack(stderr);
OS::Abort();
UNREACHABLE();
@@ -14345,11 +14592,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_AbortJS) {
+RUNTIME_FUNCTION(Runtime_AbortJS) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
- OS::PrintError("abort: %s\n", *message->ToCString());
+ OS::PrintError("abort: %s\n", message->ToCString().get());
isolate->PrintStack(stderr);
OS::Abort();
UNREACHABLE();
@@ -14357,16 +14604,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_AbortJS) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
+RUNTIME_FUNCTION(Runtime_FlattenString) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
- FlattenString(str);
- return isolate->heap()->undefined_value();
+ return *String::Flatten(str);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyContextDisposed) {
+RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
isolate->heap()->NotifyContextDisposed();
@@ -14374,49 +14620,78 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyContextDisposed) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MigrateInstance) {
+RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
+ RUNTIME_ASSERT((index->value() & 1) == 1);
+ FieldIndex field_index =
+ FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
+ if (field_index.is_inobject()) {
+ RUNTIME_ASSERT(field_index.property_index() <
+ object->map()->inobject_properties());
+ } else {
+ RUNTIME_ASSERT(field_index.outobject_array_index() <
+ object->properties()->length());
+ }
+ Handle<Object> raw_value(object->RawFastPropertyAt(field_index), isolate);
+ RUNTIME_ASSERT(raw_value->IsNumber() || raw_value->IsUninitialized());
+ return *Object::NewStorageFor(isolate, raw_value, Representation::Double());
+}
+
+
+RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
if (!object->IsJSObject()) return Smi::FromInt(0);
Handle<JSObject> js_object = Handle<JSObject>::cast(object);
if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
- JSObject::MigrateInstance(js_object);
+ // This call must not cause lazy deopts, because it's called from deferred
+ // code where we can't handle lazy deopts for lack of a suitable bailout
+ // ID. So we just try migration and signal failure if necessary,
+ // which will also trigger a deopt.
+ if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0);
return *object;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
+RUNTIME_FUNCTION(RuntimeHidden_GetFromCache) {
SealHandleScope shs(isolate);
// This is only called from codegen, so checks might be more lax.
CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
- Object* key = args[1];
+ CONVERT_ARG_CHECKED(Object, key, 1);
- int finger_index = cache->finger_index();
- Object* o = cache->get(finger_index);
- if (o == key) {
- // The fastest case: hit the same place again.
- return cache->get(finger_index + 1);
- }
+ {
+ DisallowHeapAllocation no_alloc;
- for (int i = finger_index - 2;
- i >= JSFunctionResultCache::kEntriesIndex;
- i -= 2) {
- o = cache->get(i);
+ int finger_index = cache->finger_index();
+ Object* o = cache->get(finger_index);
if (o == key) {
- cache->set_finger_index(i);
- return cache->get(i + 1);
+ // The fastest case: hit the same place again.
+ return cache->get(finger_index + 1);
+ }
+
+ for (int i = finger_index - 2;
+ i >= JSFunctionResultCache::kEntriesIndex;
+ i -= 2) {
+ o = cache->get(i);
+ if (o == key) {
+ cache->set_finger_index(i);
+ return cache->get(i + 1);
+ }
}
- }
- int size = cache->size();
- ASSERT(size <= cache->length());
+ int size = cache->size();
+ ASSERT(size <= cache->length());
- for (int i = size - 2; i > finger_index; i -= 2) {
- o = cache->get(i);
- if (o == key) {
- cache->set_finger_index(i);
- return cache->get(i + 1);
+ for (int i = size - 2; i > finger_index; i -= 2) {
+ o = cache->get(i);
+ if (o == key) {
+ cache->set_finger_index(i);
+ return cache->get(i + 1);
+ }
}
}
@@ -14434,14 +14709,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
isolate);
// This handle is nor shared, nor used later, so it's safe.
Handle<Object> argv[] = { key_handle };
- bool pending_exception;
- value = Execution::Call(isolate,
- factory,
- receiver,
- ARRAY_SIZE(argv),
- argv,
- &pending_exception);
- if (pending_exception) return Failure::Exception();
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, value,
+ Execution::Call(isolate, factory, receiver, ARRAY_SIZE(argv), argv));
}
#ifdef VERIFY_HEAP
@@ -14451,8 +14721,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
#endif
// Function invocation may have cleared the cache. Reread all the data.
- finger_index = cache_handle->finger_index();
- size = cache_handle->size();
+ int finger_index = cache_handle->finger_index();
+ int size = cache_handle->size();
// If we have spare room, put new data into it, otherwise evict post finger
// entry which is likely to be the least recently used.
@@ -14485,15 +14755,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
+RUNTIME_FUNCTION(Runtime_MessageGetStartPosition) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
return Smi::FromInt(message->start_position());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
+RUNTIME_FUNCTION(Runtime_MessageGetScript) {
SealHandleScope shs(isolate);
+ ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
return message->script();
}
@@ -14502,14 +14774,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
#ifdef DEBUG
// ListNatives is ONLY used by the fuzz-natives.js in debug mode
// Exclude the code in release mode.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
+RUNTIME_FUNCTION(Runtime_ListNatives) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
#define COUNT_ENTRY(Name, argc, ressize) + 1
int entry_count = 0
RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
+ RUNTIME_HIDDEN_FUNCTION_LIST(COUNT_ENTRY)
INLINE_FUNCTION_LIST(COUNT_ENTRY)
- INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
+ INLINE_OPTIMIZED_FUNCTION_LIST(COUNT_ENTRY);
#undef COUNT_ENTRY
Factory* factory = isolate->factory();
Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
@@ -14521,11 +14794,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
Handle<String> name; \
/* Inline runtime functions have an underscore in front of the name. */ \
if (inline_runtime_functions) { \
- name = factory->NewStringFromAscii( \
- Vector<const char>("_" #Name, StrLength("_" #Name))); \
+ name = factory->NewStringFromStaticAscii("_" #Name); \
} else { \
- name = factory->NewStringFromAscii( \
- Vector<const char>(#Name, StrLength(#Name))); \
+ name = factory->NewStringFromStaticAscii(#Name); \
} \
Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \
pair_elements->set(0, *name); \
@@ -14535,9 +14806,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
}
inline_runtime_functions = false;
RUNTIME_FUNCTION_LIST(ADD_ENTRY)
+ INLINE_OPTIMIZED_FUNCTION_LIST(ADD_ENTRY)
+ // Calling hidden runtime functions should just throw.
+ RUNTIME_HIDDEN_FUNCTION_LIST(ADD_ENTRY)
inline_runtime_functions = true;
INLINE_FUNCTION_LIST(ADD_ENTRY)
- INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
#undef ADD_ENTRY
ASSERT_EQ(index, entry_count);
Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
@@ -14546,29 +14819,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
#endif
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(String, format, 0);
- CONVERT_ARG_CHECKED(JSArray, elms, 1);
- DisallowHeapAllocation no_gc;
- String::FlatContent format_content = format->GetFlatContent();
- RUNTIME_ASSERT(format_content.IsAscii());
- Vector<const uint8_t> chars = format_content.ToOneByteVector();
- isolate->logger()->LogRuntime(Vector<const char>::cast(chars), elms);
- return isolate->heap()->undefined_value();
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
+RUNTIME_FUNCTION(Runtime_IS_VAR) {
UNREACHABLE(); // implemented as macro in the parser
return NULL;
}
#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
- RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \
- CONVERT_ARG_CHECKED(JSObject, obj, 0); \
+ RUNTIME_FUNCTION(Runtime_Has##Name) { \
+ CONVERT_ARG_CHECKED(JSObject, obj, 0); \
return isolate->heap()->ToBoolean(obj->Has##Name()); \
}
@@ -14578,24 +14837,37 @@ ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(NonStrictArgumentsElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
+ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
// Properties test sitting with elements tests - not fooling anyone.
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
-RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
+#define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
+ RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \
+ CONVERT_ARG_CHECKED(JSObject, obj, 0); \
+ return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
+ }
+
+TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
+
+#undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
+
+
+#define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
+ RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \
+ CONVERT_ARG_CHECKED(JSObject, obj, 0); \
+ return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
+ }
+
+TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
+
+#undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
+
+
+RUNTIME_FUNCTION(Runtime_HaveSameMap) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(JSObject, obj1, 0);
@@ -14604,69 +14876,64 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessCheckNeeded) {
+RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(HeapObject, obj, 0);
- return isolate->heap()->ToBoolean(obj->IsAccessCheckNeeded());
+ CONVERT_ARG_CHECKED(Object, obj, 0);
+ return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
+RUNTIME_FUNCTION(Runtime_IsObserved) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
- JSReceiver* obj = JSReceiver::cast(args[0]);
- if (obj->IsJSGlobalProxy()) {
- Object* proto = obj->GetPrototype();
- if (proto->IsNull()) return isolate->heap()->false_value();
- ASSERT(proto->IsJSGlobalObject());
- obj = JSReceiver::cast(proto);
- }
+ CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
+ ASSERT(!obj->IsJSGlobalProxy() || !obj->map()->is_observed());
return isolate->heap()->ToBoolean(obj->map()->is_observed());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
+RUNTIME_FUNCTION(Runtime_SetIsObserved) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
- if (obj->IsJSGlobalProxy()) {
- Object* proto = obj->GetPrototype();
- if (proto->IsNull()) return isolate->heap()->undefined_value();
- ASSERT(proto->IsJSGlobalObject());
- obj = handle(JSReceiver::cast(proto));
- }
- if (obj->IsJSProxy())
- return isolate->heap()->undefined_value();
+ RUNTIME_ASSERT(!obj->IsJSGlobalProxy());
+ if (obj->IsJSProxy()) return isolate->heap()->undefined_value();
+ RUNTIME_ASSERT(!obj->map()->is_observed());
- ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
- Handle<JSObject>::cast(obj)->HasFastElements()));
ASSERT(obj->IsJSObject());
JSObject::SetObserved(Handle<JSObject>::cast(obj));
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetMicrotaskPending) {
- SealHandleScope shs(isolate);
+RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_BOOLEAN_ARG_CHECKED(new_state, 0);
- bool old_state = isolate->microtask_pending();
- isolate->set_microtask_pending(new_state);
- return isolate->heap()->ToBoolean(old_state);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, microtask, 0);
+ isolate->EnqueueMicrotask(microtask);
+ return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
+RUNTIME_FUNCTION(Runtime_RunMicrotasks) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 0);
+ isolate->RunMicrotasks();
+ return isolate->heap()->undefined_value();
+}
+
+
+RUNTIME_FUNCTION(Runtime_GetObservationState) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
return isolate->heap()->observation_state();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
+RUNTIME_FUNCTION(Runtime_ObservationWeakMapCreate) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
// TODO(adamk): Currently this runtime function is only called three times per
@@ -14676,60 +14943,87 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
Handle<JSWeakMap> weakmap =
Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
- return WeakCollectionInitialize(isolate, weakmap);
+ return *WeakCollectionInitialize(isolate, weakmap);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_UnwrapGlobalProxy) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
- Object* object = args[0];
- if (object->IsJSGlobalProxy()) {
- object = object->GetPrototype(isolate);
- if (object->IsNull()) return isolate->heap()->undefined_value();
- }
- return object;
+static bool ContextsHaveSameOrigin(Handle<Context> context1,
+ Handle<Context> context2) {
+ return context1->security_token() == context2->security_token();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) {
+RUNTIME_FUNCTION(Runtime_ObserverObjectAndRecordHaveSameOrigin) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
- ASSERT(object->IsAccessCheckNeeded());
- Handle<Object> key = args.at<Object>(2);
- SaveContext save(isolate);
- isolate->set_context(observer->context());
- if (!isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
- v8::ACCESS_KEYS)) {
- return isolate->heap()->false_value();
- }
- bool access_allowed = false;
- uint32_t index = 0;
- if (key->ToArrayIndex(&index) ||
- (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) {
- access_allowed =
- isolate->MayIndexedAccess(*object, index, v8::ACCESS_GET) &&
- isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS);
- } else {
- access_allowed = isolate->MayNamedAccess(*object, *key, v8::ACCESS_GET) &&
- isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS);
- }
- return isolate->heap()->ToBoolean(access_allowed);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, record, 2);
+
+ Handle<Context> observer_context(observer->context()->native_context(),
+ isolate);
+ Handle<Context> object_context(object->GetCreationContext());
+ Handle<Context> record_context(record->GetCreationContext());
+
+ return isolate->heap()->ToBoolean(
+ ContextsHaveSameOrigin(object_context, observer_context) &&
+ ContextsHaveSameOrigin(object_context, record_context));
+}
+
+
+RUNTIME_FUNCTION(Runtime_ObjectWasCreatedInCurrentOrigin) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+
+ Handle<Context> creation_context(object->GetCreationContext(), isolate);
+ return isolate->heap()->ToBoolean(
+ ContextsHaveSameOrigin(creation_context, isolate->native_context()));
}
-static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
+RUNTIME_FUNCTION(Runtime_GetObjectContextObjectObserve) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+
+ Handle<Context> context(object->GetCreationContext(), isolate);
+ return context->native_object_observe();
+}
+
+
+RUNTIME_FUNCTION(Runtime_GetObjectContextObjectGetNotifier) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+
+ Handle<Context> context(object->GetCreationContext(), isolate);
+ return context->native_object_get_notifier();
+}
+
+
+RUNTIME_FUNCTION(Runtime_GetObjectContextNotifierPerformChange) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object_info, 0);
+
+ Handle<Context> context(object_info->GetCreationContext(), isolate);
+ return context->native_object_notifier_perform_change();
+}
+
+
+static Object* ArrayConstructorCommon(Isolate* isolate,
Handle<JSFunction> constructor,
Handle<AllocationSite> site,
Arguments* caller_args) {
+ Factory* factory = isolate->factory();
+
bool holey = false;
bool can_use_type_feedback = true;
if (caller_args->length() == 1) {
- Object* argument_one = (*caller_args)[0];
+ Handle<Object> argument_one = caller_args->at<Object>(0);
if (argument_one->IsSmi()) {
- int value = Smi::cast(argument_one)->value();
+ int value = Handle<Smi>::cast(argument_one)->value();
if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
// the array is a dictionary in this case.
can_use_type_feedback = false;
@@ -14742,8 +15036,7 @@ static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
}
}
- JSArray* array;
- MaybeObject* maybe_array;
+ Handle<JSArray> array;
if (!site.is_null() && can_use_type_feedback) {
ElementsKind to_kind = site->GetElementsKind();
if (holey && !IsFastHoleyElementsKind(to_kind)) {
@@ -14752,27 +15045,39 @@ static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
site->SetElementsKind(to_kind);
}
- maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite(
- *constructor, site);
- if (!maybe_array->To(&array)) return maybe_array;
+ // We should allocate with an initial map that reflects the allocation site
+ // advice. Therefore we use AllocateJSObjectFromMap instead of passing
+ // the constructor.
+ Handle<Map> initial_map(constructor->initial_map(), isolate);
+ if (to_kind != initial_map->elements_kind()) {
+ initial_map = Map::AsElementsKind(initial_map, to_kind);
+ }
+
+ // If we don't care to track arrays of to_kind ElementsKind, then
+ // don't emit a memento for them.
+ Handle<AllocationSite> allocation_site;
+ if (AllocationSite::GetMode(to_kind) == TRACK_ALLOCATION_SITE) {
+ allocation_site = site;
+ }
+
+ array = Handle<JSArray>::cast(factory->NewJSObjectFromMap(
+ initial_map, NOT_TENURED, true, allocation_site));
} else {
- maybe_array = isolate->heap()->AllocateJSObject(*constructor);
- if (!maybe_array->To(&array)) return maybe_array;
+ array = Handle<JSArray>::cast(factory->NewJSObject(constructor));
+
// We might need to transition to holey
ElementsKind kind = constructor->initial_map()->elements_kind();
if (holey && !IsFastHoleyElementsKind(kind)) {
kind = GetHoleyElementsKind(kind);
- maybe_array = array->TransitionElementsKind(kind);
- if (maybe_array->IsFailure()) return maybe_array;
+ JSObject::TransitionElementsKind(array, kind);
}
}
- maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0,
- DONT_INITIALIZE_ARRAY_ELEMENTS);
- if (maybe_array->IsFailure()) return maybe_array;
+ factory->NewJSArrayStorage(array, 0, 0, DONT_INITIALIZE_ARRAY_ELEMENTS);
+
ElementsKind old_kind = array->GetElementsKind();
- maybe_array = ArrayConstructInitializeElements(array, caller_args);
- if (maybe_array->IsFailure()) return maybe_array;
+ RETURN_FAILURE_ON_EXCEPTION(
+ isolate, ArrayConstructInitializeElements(array, caller_args));
if (!site.is_null() &&
(old_kind != array->GetElementsKind() ||
!can_use_type_feedback)) {
@@ -14781,11 +15086,11 @@ static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
// We must mark the allocationsite as un-inlinable.
site->SetDoNotInlineCall();
}
- return array;
+ return *array;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {
+RUNTIME_FUNCTION(RuntimeHidden_ArrayConstructor) {
HandleScope scope(isolate);
// If we get 2 arguments then they are the stub parameters (constructor, type
// info). If we get 4, then the first one is a pointer to the arguments
@@ -14810,10 +15115,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {
Handle<AllocationSite> site;
if (!type_info.is_null() &&
- *type_info != isolate->heap()->undefined_value() &&
- Cell::cast(*type_info)->value()->IsAllocationSite()) {
- site = Handle<AllocationSite>(
- AllocationSite::cast(Cell::cast(*type_info)->value()), isolate);
+ *type_info != isolate->heap()->undefined_value()) {
+ site = Handle<AllocationSite>::cast(type_info);
ASSERT(!site->SitePointsToLiteral());
}
@@ -14824,7 +15127,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalArrayConstructor) {
+RUNTIME_FUNCTION(RuntimeHidden_InternalArrayConstructor) {
HandleScope scope(isolate);
Arguments empty_args(0, NULL);
bool no_caller_args = args.length() == 1;
@@ -14847,7 +15150,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalArrayConstructor) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MaxSmi) {
+RUNTIME_FUNCTION(Runtime_MaxSmi) {
+ ASSERT(args.length() == 0);
return Smi::FromInt(Smi::kMaxValue);
}
@@ -14860,46 +15164,56 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_MaxSmi) {
FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
+#define FH(name, number_of_args, result_size) \
+ { Runtime::kHidden##name, Runtime::RUNTIME_HIDDEN, NULL, \
+ FUNCTION_ADDR(RuntimeHidden_##name), number_of_args, result_size },
+
+
#define I(name, number_of_args, result_size) \
{ Runtime::kInline##name, Runtime::INLINE, \
"_" #name, NULL, number_of_args, result_size },
+
+#define IO(name, number_of_args, result_size) \
+ { Runtime::kInlineOptimized##name, Runtime::INLINE_OPTIMIZED, \
+ "_" #name, FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
+
+
static const Runtime::Function kIntrinsicFunctions[] = {
RUNTIME_FUNCTION_LIST(F)
+ INLINE_OPTIMIZED_FUNCTION_LIST(F)
+ RUNTIME_HIDDEN_FUNCTION_LIST(FH)
INLINE_FUNCTION_LIST(I)
- INLINE_RUNTIME_FUNCTION_LIST(I)
+ INLINE_OPTIMIZED_FUNCTION_LIST(IO)
};
+#undef IO
+#undef I
+#undef FH
+#undef F
+
-MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
- Object* dictionary) {
- ASSERT(dictionary != NULL);
- ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0);
+void Runtime::InitializeIntrinsicFunctionNames(Isolate* isolate,
+ Handle<NameDictionary> dict) {
+ ASSERT(dict->NumberOfElements() == 0);
+ HandleScope scope(isolate);
for (int i = 0; i < kNumFunctions; ++i) {
- Object* name_string;
- { MaybeObject* maybe_name_string =
- heap->InternalizeUtf8String(kIntrinsicFunctions[i].name);
- if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
- }
- NameDictionary* name_dictionary = NameDictionary::cast(dictionary);
- { MaybeObject* maybe_dictionary = name_dictionary->Add(
- String::cast(name_string),
- Smi::FromInt(i),
- PropertyDetails(NONE, NORMAL, Representation::None()));
- if (!maybe_dictionary->ToObject(&dictionary)) {
- // Non-recoverable failure. Calling code must restart heap
- // initialization.
- return maybe_dictionary;
- }
- }
+ const char* name = kIntrinsicFunctions[i].name;
+ if (name == NULL) continue;
+ Handle<NameDictionary> new_dict = NameDictionary::Add(
+ dict,
+ isolate->factory()->InternalizeUtf8String(name),
+ Handle<Smi>(Smi::FromInt(i), isolate),
+ PropertyDetails(NONE, NORMAL, Representation::None()));
+ // The dictionary does not need to grow.
+ CHECK(new_dict.is_identical_to(dict));
}
- return dictionary;
}
const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
Heap* heap = name->GetHeap();
- int entry = heap->intrinsic_function_names()->FindEntry(*name);
+ int entry = heap->intrinsic_function_names()->FindEntry(name);
if (entry != kNotFound) {
Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
int function_index = Smi::cast(smi_index)->value();
@@ -14913,26 +15227,4 @@ const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
return &(kIntrinsicFunctions[static_cast<int>(id)]);
}
-
-void Runtime::PerformGC(Object* result, Isolate* isolate) {
- Failure* failure = Failure::cast(result);
- if (failure->IsRetryAfterGC()) {
- if (isolate->heap()->new_space()->AddFreshPage()) {
- return;
- }
-
- // Try to do a garbage collection; ignore it if it fails. The C
- // entry stub will throw an out-of-memory exception in that case.
- isolate->heap()->CollectGarbage(failure->allocation_space(),
- "Runtime::PerformGC");
- } else {
- // Handle last resort GC and make sure to allow future allocations
- // to grow the heap without causing GCs (if possible).
- isolate->counters()->gc_last_resort_from_js()->Increment();
- isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
- "Runtime::PerformGC");
- }
-}
-
-
} } // namespace v8::internal