#include "src/allocation-site-scopes.h"
#include "src/api.h"
#include "src/arguments.h"
+#include "src/bailout-reason.h"
#include "src/base/cpu.h"
#include "src/base/platform/platform.h"
#include "src/bootstrapper.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/utils.h"
#include "src/v8threads.h"
StrictMode name = static_cast<StrictMode>(args.smi_at(index));
+// Assert that the given argument is a number within the Int32 range
+// and convert it to int32_t. If the argument is not an Int32 call
+// IllegalOperation and return.
+#define CONVERT_INT32_ARG_CHECKED(name, index) \
+ RUNTIME_ASSERT(args[index]->IsNumber()); \
+ int32_t name = 0; \
+ RUNTIME_ASSERT(args[index]->ToInt32(&name));
+
+
static Handle<Map> ComputeObjectLiteralMap(
Handle<Context> context,
Handle<FixedArray> constant_properties,
return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
}
*is_result_from_cache = false;
- return Map::Create(handle(context->object_function()), number_of_properties);
+ return Map::Create(isolate, number_of_properties);
}
DCHECK(key->IsNumber());
double num = key->Number();
char arr[100];
- Vector<char> buffer(arr, ARRAY_SIZE(arr));
+ Vector<char> buffer(arr, arraysize(arr));
const char* str = DoubleToCString(num, buffer);
Handle<String> name = isolate->factory()->NewStringFromAsciiChecked(str);
maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name,
}
-RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) {
+RUNTIME_FUNCTION(Runtime_CreatePrivateOwnSymbol) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
+ RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
+ Handle<Symbol> symbol = isolate->factory()->NewPrivateOwnSymbol();
+ if (name->IsString()) symbol->set_name(*name);
+ return *symbol;
+}
+
+
+RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateOwnSymbol) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
DCHECK(symbol->IsUndefined());
symbol = isolate->factory()->NewPrivateSymbol();
Handle<Symbol>::cast(symbol)->set_name(*name);
+ Handle<Symbol>::cast(symbol)->set_is_own(true);
JSObject::SetProperty(Handle<JSObject>::cast(privates), name, symbol,
STRICT).Assert();
}
}
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)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, 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)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewRangeError("invalid_array_buffer_length",
+ HandleVector<Object>(NULL, 0)));
}
return *holder;
}
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)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewRangeError("invalid_typed_array_length",
+ HandleVector<Object>(NULL, 0)));
}
// All checks are done, now we can modify objects.
if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
(length > (kMaxInt / element_size))) {
- return isolate->Throw(*isolate->factory()->
- NewRangeError("invalid_typed_array_length",
- HandleVector<Object>(NULL, 0)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewRangeError("invalid_typed_array_length",
+ HandleVector<Object>(NULL, 0)));
}
size_t byte_length = length * element_size;
if (!Runtime::SetupArrayBufferAllocatingData(
isolate, buffer, byte_length, false)) {
- return isolate->Throw(*isolate->factory()->
- NewRangeError("invalid_array_buffer_length",
- HandleVector<Object>(NULL, 0)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewRangeError("invalid_array_buffer_length",
+ HandleVector<Object>(NULL, 0)));
}
holder->set_buffer(*buffer);
RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
- if (!args[0]->IsJSTypedArray())
- return isolate->Throw(*isolate->factory()->NewTypeError(
- "not_typed_array", HandleVector<Object>(NULL, 0)));
+ if (!args[0]->IsJSTypedArray()) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate,
+ NewTypeError("not_typed_array", HandleVector<Object>(NULL, 0)));
+ }
if (!args[1]->IsJSTypedArray())
return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
size_t source_length = NumberToSize(isolate, source->length());
size_t target_byte_length = NumberToSize(isolate, target->byte_length());
size_t source_byte_length = NumberToSize(isolate, source->byte_length());
- if (offset > target_length ||
- offset + source_length > target_length ||
- offset + source_length < offset) // overflow
- return isolate->Throw(*isolate->factory()->NewRangeError(
- "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
+ if (offset > target_length || offset + source_length > target_length ||
+ offset + source_length < offset) { // overflow
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewRangeError("typed_array_set_source_too_large",
+ HandleVector<Object>(NULL, 0)));
+ }
size_t target_offset = NumberToSize(isolate, target->byte_offset());
size_t source_offset = NumberToSize(isolate, source->byte_offset());
}
-#define DATA_VIEW_GETTER(TypeName, Type, Converter) \
- RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) { \
- HandleScope scope(isolate); \
- DCHECK(args.length() == 3); \
- CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
- 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->factory()->Converter(result); \
- } else { \
- return isolate->Throw(*isolate->factory()->NewRangeError( \
- "invalid_data_view_accessor_offset", \
- HandleVector<Object>(NULL, 0))); \
- } \
+#define DATA_VIEW_GETTER(TypeName, Type, Converter) \
+ RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 3); \
+ CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
+ 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->factory()->Converter(result); \
+ } else { \
+ THROW_NEW_ERROR_RETURN_FAILURE( \
+ isolate, NewRangeError("invalid_data_view_accessor_offset", \
+ HandleVector<Object>(NULL, 0))); \
+ } \
}
DATA_VIEW_GETTER(Uint8, uint8_t, NewNumberFromUint)
}
-#define DATA_VIEW_SETTER(TypeName, Type) \
- RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) { \
- HandleScope scope(isolate); \
- DCHECK(args.length() == 4); \
- CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
- 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( \
- isolate, holder, offset, is_little_endian, v)) { \
- return isolate->heap()->undefined_value(); \
- } else { \
- return isolate->Throw(*isolate->factory()->NewRangeError( \
- "invalid_data_view_accessor_offset", \
- HandleVector<Object>(NULL, 0))); \
- } \
+#define DATA_VIEW_SETTER(TypeName, Type) \
+ RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 4); \
+ CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
+ 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(isolate, holder, offset, is_little_endian, v)) { \
+ return isolate->heap()->undefined_value(); \
+ } else { \
+ THROW_NEW_ERROR_RETURN_FAILURE( \
+ isolate, NewRangeError("invalid_data_view_accessor_offset", \
+ HandleVector<Object>(NULL, 0))); \
+ } \
}
DATA_VIEW_SETTER(Uint8, uint8_t)
Handle<Object> key(table->KeyAt(i), isolate);
if (table->IsKey(*key)) {
entries->set(number_of_non_hole_elements++, *key);
- entries->set(number_of_non_hole_elements++, table->Lookup(key));
+ Object* value = table->Lookup(key);
+ entries->set(number_of_non_hole_elements++, value);
}
}
DCHECK_EQ(table->NumberOfElements() * 2, number_of_non_hole_elements);
}
} else {
// Get attributes.
- LookupIterator it(obj, name, LookupIterator::CHECK_OWN);
+ LookupIterator it(obj, name, LookupIterator::HIDDEN);
Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
if (!maybe.has_value) return MaybeHandle<Object>();
attrs = maybe.value;
if (attrs == ABSENT) return factory->undefined_value();
// Get AccessorPair if present.
- if (it.state() == LookupIterator::PROPERTY &&
- it.property_kind() == LookupIterator::ACCESSOR &&
+ if (it.state() == LookupIterator::ACCESSOR &&
it.GetAccessors()->IsAccessorPair()) {
maybe_accessors = Handle<AccessorPair>::cast(it.GetAccessors());
}
}
+RUNTIME_FUNCTION(Runtime_ToMethod) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
+ Handle<JSFunction> clone = JSFunction::CloneClosure(fun);
+ Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
+ JSObject::SetOwnPropertyIgnoreAttributes(clone, home_object_symbol,
+ home_object, DONT_ENUM).Assert();
+ return *clone;
+}
+
+
+RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
+ DCHECK(args.length() == 0);
+ return isolate->heap()->home_object_symbol();
+}
+
+
+RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 3);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
+
+ if (home_object->IsAccessCheckNeeded() &&
+ !isolate->MayNamedAccess(home_object, name, v8::ACCESS_GET)) {
+ isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_GET);
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
+ }
+
+ PrototypeIterator iter(isolate, home_object);
+ Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
+ if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
+
+ LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
+ return *result;
+}
+
+
RUNTIME_FUNCTION(Runtime_IsExtensible) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
HandleScope scope(isolate);
Handle<Object> args[1] = { name };
- Handle<Object> error = isolate->factory()->NewTypeError(
- "var_redeclaration", HandleVector(args, 1));
- return isolate->Throw(*error);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError("var_redeclaration", HandleVector(args, 1)));
}
PropertyAttributes attr, bool is_var,
bool is_const, bool is_function) {
// Do the lookup own properties only, see ES5 erratum.
- LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN);
+ LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
- DCHECK(maybe.has_value);
- PropertyAttributes old_attributes = maybe.value;
+ if (!maybe.has_value) return isolate->heap()->exception();
- if (old_attributes != ABSENT) {
+ if (it.IsFound()) {
+ PropertyAttributes old_attributes = maybe.value;
// The name was declared before; check for conflicting re-declarations.
if (is_const) return ThrowRedeclarationError(isolate, name);
Handle<GlobalObject> global = isolate->global_object();
// Lookup the property as own on the global object.
- LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN);
+ LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
DCHECK(maybe.has_value);
PropertyAttributes old_attributes = maybe.value;
// Ignore if we can't reconfigure the value.
if ((old_attributes & DONT_DELETE) != 0) {
if ((old_attributes & READ_ONLY) != 0 ||
- it.property_kind() == LookupIterator::ACCESSOR) {
+ it.state() == LookupIterator::ACCESSOR) {
return *value;
}
attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
// code can run in between that modifies the declared property.
DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
- LookupIterator it(holder, name, LookupIterator::CHECK_HIDDEN);
+ LookupIterator it(holder, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
if (!maybe.has_value) return isolate->heap()->exception();
PropertyAttributes old_attributes = maybe.value;
// Ignore if we can't reconfigure the value.
if ((old_attributes & DONT_DELETE) != 0) {
if ((old_attributes & READ_ONLY) != 0 ||
- it.property_kind() == LookupIterator::ACCESSOR) {
+ it.state() == LookupIterator::ACCESSOR) {
return *value;
}
attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
+ CONVERT_INT32_ARG_CHECKED(index, 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
// Due to the way the JS calls are constructed this must be less than the
// length of a string, i.e. it is always a Smi. We check anyway for security.
- CONVERT_SMI_ARG_CHECKED(index, 2);
- CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
RUNTIME_ASSERT(index >= 0);
RUNTIME_ASSERT(index <= subject->length());
isolate->counters()->regexp_entry_runtime()->Increment();
RUNTIME_FUNCTION(Runtime_RegExpInitializeObject) {
HandleScope scope(isolate);
- DCHECK(args.length() == 5);
+ DCHECK(args.length() == 6);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
// If source is the empty string we set it to "(?:)" instead as
CONVERT_ARG_HANDLE_CHECKED(Object, multiline, 4);
if (!multiline->IsTrue()) multiline = isolate->factory()->false_value();
+ CONVERT_ARG_HANDLE_CHECKED(Object, sticky, 5);
+ if (!sticky->IsTrue()) sticky = isolate->factory()->false_value();
+
Map* map = regexp->map();
Object* constructor = map->constructor();
- if (constructor->IsJSFunction() &&
+ if (!FLAG_harmony_regexps &&
+ constructor->IsJSFunction() &&
JSFunction::cast(constructor)->initial_map() == map) {
// If we still have the original map, set in-object properties directly.
regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, *source);
return *regexp;
}
- // Map has changed, so use generic, but slower, method.
+ // Map has changed, so use generic, but slower, method. We also end here if
+ // the --harmony-regexp flag is set, because the initial map does not have
+ // space for the 'sticky' flag, since it is from the snapshot, but must work
+ // both with and without --harmony-regexp. When sticky comes out from under
+ // the flag, we will be able to use the fast initial map.
PropertyAttributes final =
static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
PropertyAttributes writable =
regexp, factory->ignore_case_string(), ignoreCase, final).Check();
JSObject::SetOwnPropertyIgnoreAttributes(
regexp, factory->multiline_string(), multiline, final).Check();
+ if (FLAG_harmony_regexps) {
+ JSObject::SetOwnPropertyIgnoreAttributes(
+ regexp, factory->sticky_string(), sticky, final).Check();
+ }
JSObject::SetOwnPropertyIgnoreAttributes(
regexp, factory->last_index_string(), zero, writable).Check();
return *regexp;
}
+RUNTIME_FUNCTION(Runtime_FunctionIsConciseMethod) {
+ SealHandleScope shs(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_CHECKED(JSFunction, f, 0);
+ return isolate->heap()->ToBoolean(f->shared()->is_concise_method());
+}
+
+
RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
"generator_finished" : "generator_running";
Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
- Handle<Object> error = isolate->factory()->NewError(message, argv);
- return isolate->Throw(*error);
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewError(message, argv));
}
class ReplacementStringBuilder {
public:
- ReplacementStringBuilder(Heap* heap,
- Handle<String> subject,
+ ReplacementStringBuilder(Heap* heap, Handle<String> subject,
int estimated_part_count)
: heap_(heap),
array_builder_(heap->isolate(), estimated_part_count),
subject_(subject),
character_count_(0),
- is_ascii_(subject->IsOneByteRepresentation()) {
+ is_one_byte_(subject->IsOneByteRepresentation()) {
// Require a non-zero initial size. Ensures that doubling the size to
// extend the array will work.
DCHECK(estimated_part_count > 0);
DCHECK(length > 0);
AddElement(*string);
if (!string->IsOneByteRepresentation()) {
- is_ascii_ = false;
+ is_one_byte_ = false;
}
IncrementCharacterCount(length);
}
}
Handle<String> joined_string;
- if (is_ascii_) {
+ if (is_one_byte_) {
Handle<SeqOneByteString> seq;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, seq,
array_builder_.length());
joined_string = Handle<String>::cast(seq);
} else {
- // Non-ASCII.
+ // Two-byte.
Handle<SeqTwoByteString> seq;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, seq,
FixedArrayBuilder array_builder_;
Handle<String> subject_;
int character_count_;
- bool is_ascii_;
+ bool is_one_byte_;
};
String::FlatContent content = replacement->GetFlatContent();
DCHECK(content.IsFlat());
bool simple = false;
- if (content.IsAscii()) {
+ if (content.IsOneByte()) {
simple = ParseReplacementPattern(&parts_,
content.ToOneByteVector(),
capture_count,
}
-void FindAsciiStringIndices(Vector<const uint8_t> subject,
- char pattern,
- ZoneList<int>* indices,
- unsigned int limit,
- Zone* zone) {
+void FindOneByteStringIndices(Vector<const uint8_t> subject, char pattern,
+ ZoneList<int>* indices, unsigned int limit,
+ Zone* zone) {
DCHECK(limit > 0);
// Collect indices of pattern in subject using memchr.
// Stop after finding at most limit values.
String::FlatContent pattern_content = pattern->GetFlatContent();
DCHECK(subject_content.IsFlat());
DCHECK(pattern_content.IsFlat());
- if (subject_content.IsAscii()) {
+ if (subject_content.IsOneByte()) {
Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
- if (pattern_content.IsAscii()) {
+ if (pattern_content.IsOneByte()) {
Vector<const uint8_t> pattern_vector =
pattern_content.ToOneByteVector();
if (pattern_vector.length() == 1) {
- FindAsciiStringIndices(subject_vector,
- pattern_vector[0],
- indices,
- limit,
- zone);
+ FindOneByteStringIndices(subject_vector, pattern_vector[0], indices,
+ limit, zone);
} else {
FindStringIndices(isolate,
subject_vector,
}
} else {
Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
- if (pattern_content.IsAscii()) {
+ if (pattern_content.IsOneByte()) {
Vector<const uint8_t> pattern_vector =
pattern_content.ToOneByteVector();
if (pattern_vector.length() == 1) {
int result_pos = 0;
MaybeHandle<SeqString> maybe_res;
- if (ResultSeqString::kHasAsciiEncoding) {
+ if (ResultSeqString::kHasOneByteEncoding) {
maybe_res = isolate->factory()->NewRawOneByteString(result_len);
} else {
maybe_res = isolate->factory()->NewRawTwoByteString(result_len);
if (new_length == 0) return isolate->heap()->empty_string();
Handle<ResultSeqString> answer;
- if (ResultSeqString::kHasAsciiEncoding) {
+ if (ResultSeqString::kHasOneByteEncoding) {
answer = Handle<ResultSeqString>::cast(
isolate->factory()->NewRawOneByteString(new_length).ToHandleChecked());
} else {
pat = String::Flatten(pat);
DisallowHeapAllocation no_gc; // ensure vectors stay valid
- // Extract flattened substrings of cons strings before determining asciiness.
+ // Extract flattened substrings of cons strings before getting encoding.
String::FlatContent seq_sub = sub->GetFlatContent();
String::FlatContent seq_pat = pat->GetFlatContent();
// dispatch on type of strings
- if (seq_pat.IsAscii()) {
+ if (seq_pat.IsOneByte()) {
Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
- if (seq_sub.IsAscii()) {
+ if (seq_sub.IsOneByte()) {
return SearchString(isolate,
seq_sub.ToOneByteVector(),
pat_vector,
start_index);
}
Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
- if (seq_sub.IsAscii()) {
+ if (seq_sub.IsOneByte()) {
return SearchString(isolate,
seq_sub.ToOneByteVector(),
pat_vector,
String::FlatContent sub_content = sub->GetFlatContent();
String::FlatContent pat_content = pat->GetFlatContent();
- if (pat_content.IsAscii()) {
+ if (pat_content.IsOneByte()) {
Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
- if (sub_content.IsAscii()) {
+ if (sub_content.IsOneByte()) {
position = StringMatchBackwards(sub_content.ToOneByteVector(),
pat_vector,
start_index);
}
} else {
Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
- if (sub_content.IsAscii()) {
+ if (sub_content.IsOneByte()) {
position = StringMatchBackwards(sub_content.ToOneByteVector(),
pat_vector,
start_index);
Handle<Object> key) {
if (object->IsUndefined() || object->IsNull()) {
Handle<Object> args[2] = { key, object };
- return isolate->Throw<Object>(
- isolate->factory()->NewTypeError("non_object_property_load",
- HandleVector(args, 2)));
+ THROW_NEW_ERROR(isolate, NewTypeError("non_object_property_load",
+ HandleVector(args, 2)),
+ Object);
}
// Check if the given key is an array index.
}
// Lookup cache miss. Perform lookup and update the cache if
// appropriate.
- LookupResult result(isolate);
- receiver->LookupOwn(key, &result);
- if (result.IsField()) {
- FieldIndex field_index = result.GetFieldIndex();
+ LookupIterator it(receiver, key, LookupIterator::OWN);
+ if (it.state() == LookupIterator::DATA &&
+ it.property_details().type() == FIELD) {
+ FieldIndex field_index = it.GetFieldIndex();
// Do not track double fields in the keyed lookup cache. Reading
// double values requires boxing.
- if (!result.representation().IsDouble()) {
+ if (!it.representation().IsDouble()) {
keyed_lookup_cache->Update(receiver_map, key,
field_index.GetKeyedLookupCacheIndex());
}
AllowHeapAllocation allow_allocation;
- return *JSObject::FastPropertyAt(receiver, result.representation(),
+ return *JSObject::FastPropertyAt(receiver, it.representation(),
field_index);
}
} else {
// Transform getter or setter into something DefineAccessor can handle.
static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
Handle<Object> component) {
- if (component->IsUndefined()) return isolate->factory()->null_value();
+ if (component->IsUndefined()) return isolate->factory()->undefined_value();
Handle<FunctionTemplateInfo> info =
Handle<FunctionTemplateInfo>::cast(component);
return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
- // Check access rights if needed.
- if (js_object->IsAccessCheckNeeded() &&
- !isolate->MayNamedAccess(js_object, name, v8::ACCESS_SET)) {
- return isolate->heap()->undefined_value();
+ LookupIterator it(js_object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
+ if (it.IsFound() && it.state() == LookupIterator::ACCESS_CHECK) {
+ if (!isolate->MayNamedAccess(js_object, name, v8::ACCESS_SET)) {
+ return isolate->heap()->undefined_value();
+ }
+ it.Next();
}
- 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
- // map.
- if (lookup.IsFound() &&
- (attr != lookup.GetAttributes() || lookup.IsPropertyCallbacks())) {
+ // a property.
+ if (it.state() == LookupIterator::ACCESSOR) {
// Use IgnoreAttributes version since a readonly property may be
// overridden and SetProperty does not allow this.
Handle<Object> result;
isolate, result,
JSObject::SetOwnPropertyIgnoreAttributes(
js_object, name, obj_value, attr,
- JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
- JSReceiver::MAY_BE_STORE_FROM_KEYED,
JSObject::DONT_FORCE_FIELD));
return *result;
}
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
- Runtime::DefineObjectProperty(
- js_object, name, obj_value, attr,
- JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED));
+ Runtime::DefineObjectProperty(js_object, name, obj_value, attr));
return *result;
}
StrictMode strict_mode) {
if (object->IsUndefined() || object->IsNull()) {
Handle<Object> args[2] = { key, object };
- Handle<Object> error =
- isolate->factory()->NewTypeError("non_object_property_store",
- HandleVector(args, 2));
- return isolate->Throw<Object>(error);
+ THROW_NEW_ERROR(isolate, NewTypeError("non_object_property_store",
+ HandleVector(args, 2)),
+ Object);
}
if (object->IsJSProxy()) {
JSObject::ValidateElements(js_object);
if (js_object->HasExternalArrayElements() ||
js_object->HasFixedTypedArrayElements()) {
- if (!value->IsNumber() && !value->IsUndefined()) {
+ if (!value->IsNumber() && !value->IsFloat32x4() &&
+ !value->IsFloat64x2() && !value->IsInt32x4() &&
+ !value->IsUndefined()) {
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, Execution::ToNumber(isolate, value), Object);
}
if (!object->IsJSObject()) return value;
Handle<JSObject> js_object = Handle<JSObject>::cast(object);
if (js_object->HasExternalArrayElements()) {
- if (!value->IsNumber() && !value->IsUndefined()) {
+ if (!value->IsNumber() && !value->IsFloat32x4() &&
+ !value->IsFloat64x2() && !value->IsInt32x4() &&
+ !value->IsUndefined()) {
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, Execution::ToNumber(isolate, value), Object);
}
}
-MaybeHandle<Object> Runtime::DefineObjectProperty(
- Handle<JSObject> js_object,
- Handle<Object> key,
- Handle<Object> value,
- PropertyAttributes attr,
- JSReceiver::StoreFromKeyed store_from_keyed) {
+MaybeHandle<Object> Runtime::DefineObjectProperty(Handle<JSObject> js_object,
+ Handle<Object> key,
+ Handle<Object> value,
+ PropertyAttributes attr) {
Isolate* isolate = js_object->GetIsolate();
// Check if the given key is an array index.
uint32_t index;
SLOPPY, false, DEFINE_PROPERTY);
} else {
if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
- return JSObject::SetOwnPropertyIgnoreAttributes(
- js_object, name, value, attr, JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
- store_from_keyed);
+ return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value,
+ attr);
}
}
return JSObject::SetElement(js_object, index, value, attr,
SLOPPY, false, DEFINE_PROPERTY);
} else {
- return JSObject::SetOwnPropertyIgnoreAttributes(
- js_object, name, value, attr, JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
- store_from_keyed);
+ return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value,
+ attr);
}
}
#ifdef DEBUG
uint32_t index = 0;
DCHECK(!key->ToArrayIndex(&index));
- LookupIterator it(object, key, LookupIterator::CHECK_OWN_REAL);
+ LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
- DCHECK(maybe.has_value);
+ if (!maybe.has_value) return isolate->heap()->exception();
RUNTIME_ASSERT(!it.IsFound());
#endif
bool duplicate;
if (key->IsName()) {
LookupIterator it(object, Handle<Name>::cast(key),
- LookupIterator::CHECK_OWN_REAL);
+ LookupIterator::OWN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
DCHECK(maybe.has_value);
duplicate = it.IsFound();
}
if (duplicate) {
Handle<Object> args[1] = { key };
- Handle<Object> error = isolate->factory()->NewTypeError(
- "duplicate_template_property", HandleVector(args, 1));
- return isolate->Throw(*error);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate,
+ NewTypeError("duplicate_template_property", HandleVector(args, 1)));
}
#endif
}
+// Adds an element to an array.
+// This is used to create an indexed data property into an array.
+RUNTIME_FUNCTION(Runtime_AddElement) {
+ HandleScope scope(isolate);
+ RUNTIME_ASSERT(args.length() == 4);
+
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
+ CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
+ RUNTIME_ASSERT(
+ (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
+ // Compute attributes.
+ PropertyAttributes attributes =
+ static_cast<PropertyAttributes>(unchecked_attributes);
+
+ uint32_t index = 0;
+ key->ToArrayIndex(&index);
+
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, JSObject::SetElement(object, index, value, attributes,
+ SLOPPY, false, DEFINE_PROPERTY));
+ return *result;
+}
+
+
RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 2);
DCHECK(args.length() == 1);
Debug* debug = isolate->debug();
if (!debug->IsStepping()) return isolate->heap()->undefined_value();
- CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
+
HandleScope scope(isolate);
- // When leaving the callback, step out has been activated, but not performed
- // if we do not leave the builtin. To be able to step into the callback
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ RUNTIME_ASSERT(object->IsJSFunction() || object->IsJSGeneratorObject());
+ Handle<JSFunction> fun;
+ if (object->IsJSFunction()) {
+ fun = Handle<JSFunction>::cast(object);
+ } else {
+ fun = Handle<JSFunction>(
+ Handle<JSGeneratorObject>::cast(object)->function(), isolate);
+ }
+ // When leaving the function, step out has been activated, but not performed
+ // if we do not leave the builtin. To be able to step into the function
// again, we need to clear the step out at this point.
debug->ClearStepOut();
- debug->FloodWithOneShot(callback);
+ debug->FloodWithOneShot(fun);
return isolate->heap()->undefined_value();
}
DCHECK(args.length() == 1);
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
- isolate->debug()->PushPromise(promise);
+ isolate->PushPromise(promise);
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
DCHECK(args.length() == 0);
SealHandleScope shs(isolate);
- isolate->debug()->PopPromise();
+ isolate->PopPromise();
return isolate->heap()->undefined_value();
}
HandleScope scope(isolate);
if (raw_key->IsSymbol()) {
+ Handle<Symbol> symbol = Handle<Symbol>::cast(raw_key);
+ if (symbol->Equals(isolate->native_context()->iterator_symbol())) {
+ return isolate->native_context()->array_values_iterator();
+ }
// Lookup in the initial Object.prototype object.
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
if (String::Equals(isolate->factory()->callee_string(), key)) {
JSFunction* function = frame->function();
if (function->shared()->strict_mode() == STRICT) {
- return isolate->Throw(*isolate->factory()->NewTypeError(
- "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError("strict_arguments_callee",
+ HandleVector<Object>(NULL, 0)));
}
return function;
}
RUNTIME_FUNCTION(Runtime_NewString) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
- CONVERT_SMI_ARG_CHECKED(length, 0);
+ CONVERT_INT32_ARG_CHECKED(length, 0);
CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
if (length == 0) return isolate->heap()->empty_string();
Handle<String> result;
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
- CONVERT_SMI_ARG_CHECKED(new_length, 1);
+ CONVERT_INT32_ARG_CHECKED(new_length, 1);
RUNTIME_ASSERT(new_length >= 0);
return *SeqString::Truncate(string, new_length);
}
String::FlatContent flat = subject->GetFlatContent();
// ECMA-262 section 15.1.2.3, empty string is NaN
- if (flat.IsAscii()) {
+ if (flat.IsOneByte()) {
value = StringToInt(
isolate->unicode_cache(), flat.ToOneByteVector(), radix);
} else {
current_length += char_length;
if (current_length > String::kMaxLength) {
AllowHeapAllocation allocate_error_and_return;
- return isolate->ThrowInvalidStringLength();
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate,
+ NewInvalidStringLengthError());
}
}
// Try again with the real length. Return signed if we need
bool changed = false;
uintptr_t or_acc = 0;
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)) {
- const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
- or_acc |= w;
- if (AsciiRangeMask(w, lo, hi) != 0) {
- changed = true;
- break;
+
+ // dst is newly allocated and always aligned.
+ DCHECK(IsAligned(reinterpret_cast<intptr_t>(dst), sizeof(uintptr_t)));
+ // Only attempt processing one word at a time if src is also aligned.
+ if (IsAligned(reinterpret_cast<intptr_t>(src), sizeof(uintptr_t))) {
+ // Process the prefix of the input that requires no conversion one aligned
+ // (machine) word at a time.
+ while (src <= limit - sizeof(uintptr_t)) {
+ const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
+ or_acc |= w;
+ if (AsciiRangeMask(w, lo, hi) != 0) {
+ changed = true;
+ break;
+ }
+ *reinterpret_cast<uintptr_t*>(dst) = w;
+ src += sizeof(uintptr_t);
+ dst += sizeof(uintptr_t);
+ }
+ // Process the remainder of the input performing conversion when
+ // required one word at a time.
+ while (src <= limit - sizeof(uintptr_t)) {
+ 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
+ // conversion and we know that the distance between cases is
+ // 1 << 5.
+ *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
+ src += sizeof(uintptr_t);
+ dst += sizeof(uintptr_t);
}
- *reinterpret_cast<uintptr_t*>(dst) = w;
- src += sizeof(uintptr_t);
- dst += sizeof(uintptr_t);
- }
- // Process the remainder of the input performing conversion when
- // required one word at a time.
- while (src <= limit - sizeof(uintptr_t)) {
- 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
- // conversion and we know that the distance between cases is
- // 1 << 5.
- *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
- src += sizeof(uintptr_t);
- dst += sizeof(uintptr_t);
}
-#endif
// Process the last few bytes of the input (or the whole input if
// unaligned access is not supported).
while (src < limit) {
++src;
++dst;
}
- if ((or_acc & kAsciiMask) != 0) {
- return false;
- }
+
+ if ((or_acc & kAsciiMask) != 0) return false;
DCHECK(CheckFastAsciiConvert(
saved_dst, saved_src, length, changed, Converter::kIsToLower));
}
-// Copies ASCII characters to the given fixed array looking up
+// Copies Latin1 characters to the given fixed array looking up
// one-char strings in the cache. Gives up on the first char that is
// not in the cache and fills the remainder with smi zeros. Returns
// the length of the successfully copied prefix.
-static int CopyCachedAsciiCharsToArray(Heap* heap,
- const uint8_t* chars,
- FixedArray* elements,
- int length) {
+static int CopyCachedOneByteCharsToArray(Heap* heap, const uint8_t* chars,
+ FixedArray* elements, int length) {
DisallowHeapAllocation no_gc;
- FixedArray* ascii_cache = heap->single_character_string_cache();
+ FixedArray* one_byte_cache = heap->single_character_string_cache();
Object* undefined = heap->undefined_value();
int i;
WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
for (i = 0; i < length; ++i) {
- Object* value = ascii_cache->get(chars[i]);
+ Object* value = one_byte_cache->get(chars[i]);
if (value == undefined) break;
elements->set(i, value, mode);
}
DisallowHeapAllocation no_gc;
String::FlatContent content = s->GetFlatContent();
- if (content.IsAscii()) {
+ if (content.IsOneByte()) {
Vector<const uint8_t> chars = content.ToOneByteVector();
// Note, this will initialize all elements (not only the prefix)
// to prevent GC from seeing partially initialized array.
- position = CopyCachedAsciiCharsToArray(isolate->heap(),
- chars.start(),
- *elements,
- length);
+ position = CopyCachedOneByteCharsToArray(isolate->heap(), chars.start(),
+ *elements, length);
} else {
MemsetPointer(elements->data_start(),
isolate->heap()->undefined_value(),
}
+RUNTIME_FUNCTION(Runtime_AllocateFloat32x4) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 0);
+
+ float32x4_value_t zero = {{0, 0, 0, 0}};
+ return *isolate->factory()->NewFloat32x4(zero);
+}
+
+
+RUNTIME_FUNCTION(Runtime_AllocateFloat64x2) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 0);
+
+ float64x2_value_t zero = {{0, 0}};
+ return *isolate->factory()->NewFloat64x2(zero);
+}
+
+
+RUNTIME_FUNCTION(Runtime_AllocateInt32x4) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 0);
+
+ int32x4_value_t zero = {{0, 0, 0, 0}};
+ return *isolate->factory()->NewInt32x4(zero);
+}
+
+
RUNTIME_FUNCTION(Runtime_NumberAdd) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
- if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
- CONVERT_SMI_ARG_CHECKED(array_length, 1);
+ int32_t array_length;
+ if (!args[1]->ToInt32(&array_length)) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
+ }
CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
size_t actual_array_length = 0;
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
- if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
- CONVERT_SMI_ARG_CHECKED(array_length, 1);
+ int32_t array_length;
+ if (!args[1]->ToInt32(&array_length)) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
+ }
CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
RUNTIME_ASSERT(array->HasFastObjectElements());
RUNTIME_ASSERT(array_length >= 0);
int max_nof_separators =
(String::kMaxLength + separator_length - 1) / separator_length;
if (max_nof_separators < (array_length - 1)) {
- return isolate->ThrowInvalidStringLength();
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
}
int length = (array_length - 1) * separator_length;
for (int i = 0; i < array_length; i++) {
}
DCHECK(sink == end);
- // Use %_FastAsciiArrayJoin instead.
+ // Use %_FastOneByteArrayJoin instead.
DCHECK(!answer->IsOneByteRepresentation());
return *answer;
}
// Find total length of join result.
int string_length = 0;
- bool is_ascii = separator->IsOneByteRepresentation();
+ bool is_one_byte = separator->IsOneByteRepresentation();
bool overflow = false;
CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length());
RUNTIME_ASSERT(elements_length <= elements_array->elements()->length());
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 (is_one_byte && !string->IsOneByteRepresentation()) {
+ is_one_byte = false;
}
if (length > String::kMaxLength ||
String::kMaxLength - length < string_length) {
// 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();
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
}
- if (is_ascii) {
+ if (is_one_byte) {
Handle<SeqOneByteString> result = isolate->factory()->NewRawOneByteString(
string_length).ToHandleChecked();
JoinSparseArrayWithSeparator<uint8_t>(
int r;
String::FlatContent x_content = x->GetFlatContent();
String::FlatContent y_content = y->GetFlatContent();
- if (x_content.IsAscii()) {
+ if (x_content.IsOneByte()) {
Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
- if (y_content.IsAscii()) {
+ if (y_content.IsOneByte()) {
Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
} else {
}
} else {
Vector<const uc16> x_chars = x_content.ToUC16Vector();
- if (y_content.IsAscii()) {
+ if (y_content.IsOneByte()) {
Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
} else {
DCHECK(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
Factory* factory = isolate->factory();
- double y[2];
+ double y[2] = {0.0, 0.0};
int n = fdlibm::rempio2(x, y);
Handle<FixedArray> array = factory->NewFixedArray(3);
Handle<HeapNumber> y0 = factory->NewHeapNumber(y[0]);
DCHECK(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- float xf = static_cast<float>(x);
+ float xf = DoubleToFloat32(x);
return *isolate->factory()->NewNumber(xf);
}
CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
Handle<Context> context(isolate->context());
PretenureFlag pretenure_flag = NOT_TENURED;
- return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
- shared, context, pretenure_flag);
+ return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
+ pretenure_flag);
}
// If the constructor isn't a proper function we throw a type error.
if (!constructor->IsJSFunction()) {
Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
- Handle<Object> type_error =
- isolate->factory()->NewTypeError("not_constructor", arguments);
- return isolate->Throw(*type_error);
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate,
+ NewTypeError("not_constructor", arguments));
}
Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
// case generated code bailouts here, since function has no initial_map.
if (!function->should_have_prototype() && !function->shared()->bound()) {
Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
- Handle<Object> type_error =
- isolate->factory()->NewTypeError("not_constructor", arguments);
- return isolate->Throw(*type_error);
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate,
+ NewTypeError("not_constructor", arguments));
}
Debug* debug = isolate->debug();
}
-RUNTIME_FUNCTION(Runtime_CompileUnoptimized) {
+RUNTIME_FUNCTION(Runtime_CompileLazy) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
Handle<Code> code;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, code,
- Compiler::GetUnoptimizedCode(function));
+ Compiler::GetLazyCode(function));
+ DCHECK(code->kind() == Code::FUNCTION ||
+ code->kind() == Code::OPTIMIZED_FUNCTION);
function->ReplaceCode(*code);
-
- // All done. Return the compiled code.
- DCHECK(function->is_compiled());
- DCHECK(function->code()->kind() == Code::FUNCTION ||
- (FLAG_always_opt &&
- function->code()->kind() == Code::OPTIMIZED_FUNCTION));
return *code;
}
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 (!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) {
isolate->DebuggerHasBreakPoints() ? "T" : "F");
}
function->ReplaceCode(*unoptimized);
+ return function->code();
+ }
+
+ Compiler::ConcurrencyMode mode =
+ concurrent ? Compiler::CONCURRENT : Compiler::NOT_CONCURRENT;
+ Handle<Code> code;
+ if (Compiler::GetOptimizedCode(function, unoptimized, mode).ToHandle(&code)) {
+ function->ReplaceCode(*code);
} 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);
- }
+ function->ReplaceCode(function->shared()->code());
}
DCHECK(function->code()->kind() == Code::FUNCTION ||
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+ // The following two assertions are lifted from the DCHECKs inside
+ // JSFunction::MarkForOptimization().
+ RUNTIME_ASSERT(!function->shared()->is_generator());
+ RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
+ (function->code()->kind() == Code::FUNCTION &&
+ function->code()->optimizable()));
- if (!function->IsOptimizable() &&
- !function->IsMarkedForConcurrentOptimization() &&
- !function->IsInOptimizationQueue()) {
- return isolate->heap()->undefined_value();
- }
+ // If the function is optimized, just return.
+ if (function->IsOptimized()) return isolate->heap()->undefined_value();
function->MarkForOptimization();
if (args.length() == 2 &&
unoptimized->kind() == Code::FUNCTION) {
CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
- if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr")) && FLAG_use_osr) {
+ if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("osr")) && FLAG_use_osr) {
// Start patching from the currently patched loop nesting level.
DCHECK(BackEdgeTable::Verify(isolate, unoptimized));
isolate->runtime_profiler()->AttemptOnStackReplacement(
*function, Code::kMaxLoopNestingMarker);
- } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent")) &&
+ } else if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
isolate->concurrent_recompilation_enabled()) {
function->MarkForConcurrentOptimization();
}
bool sync_with_compiler_thread = true;
if (args.length() == 2) {
CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
- if (sync->IsOneByteEqualTo(STATIC_ASCII_VECTOR("no sync"))) {
+ if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
sync_with_compiler_thread = false;
}
}
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
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);
+ CONVERT_INT32_ARG_CHECKED(offset, 3);
+ CONVERT_INT32_ARG_CHECKED(argc, 4);
RUNTIME_ASSERT(offset >= 0);
// Loose upper bound to allow fuzzing. We'll most likely run out of
// stack space before hitting this limit.
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);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError("with_expression", HandleVector(&handle, 1)));
}
}
case MUTABLE_CHECK_INITIALIZED:
case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
if (value->IsTheHole()) {
- Handle<Object> reference_error =
+ Handle<Object> error;
+ MaybeHandle<Object> maybe_error =
isolate->factory()->NewReferenceError("not_defined",
HandleVector(&name, 1));
- return MakePair(isolate->Throw(*reference_error), NULL);
+ if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
+ return MakePair(isolate->heap()->exception(), NULL);
}
// FALLTHROUGH
case MUTABLE_IS_INITIALIZED:
if (throw_error) {
// The property doesn't exist - throw exception.
- Handle<Object> reference_error =
- isolate->factory()->NewReferenceError("not_defined",
- HandleVector(&name, 1));
- return MakePair(isolate->Throw(*reference_error), NULL);
+ Handle<Object> error;
+ MaybeHandle<Object> maybe_error = isolate->factory()->NewReferenceError(
+ "not_defined", HandleVector(&name, 1));
+ if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
+ return MakePair(isolate->heap()->exception(), NULL);
} else {
// The property doesn't exist - return undefined.
return MakePair(isolate->heap()->undefined_value(),
Handle<Context>::cast(holder)->set(index, *value);
} else if (strict_mode == STRICT) {
// Setting read only property in strict mode.
- Handle<Object> error =
- isolate->factory()->NewTypeError("strict_cannot_assign",
- HandleVector(&name, 1));
- return isolate->Throw(*error);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate,
+ NewTypeError("strict_cannot_assign", HandleVector(&name, 1)));
}
return *value;
}
object = Handle<JSReceiver>::cast(holder);
} else if (strict_mode == STRICT) {
// If absent in strict mode: throw.
- Handle<Object> error = isolate->factory()->NewReferenceError(
- "not_defined", HandleVector(&name, 1));
- return isolate->Throw(*error);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewReferenceError("not_defined", HandleVector(&name, 1)));
} else {
// If absent in sloppy mode: add the property to the global object.
object = Handle<JSReceiver>(context->global_object());
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
- Handle<Object> reference_error =
- isolate->factory()->NewReferenceError("not_defined",
- HandleVector(&name, 1));
- return isolate->Throw(*reference_error);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewReferenceError("not_defined", HandleVector(&name, 1)));
+}
+
+
+RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 0);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewReferenceError("non_method", HandleVector<Object>(NULL, 0)));
+}
+
+
+RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 0);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate,
+ NewReferenceError("unsupported_super", HandleVector<Object>(NULL, 0)));
}
RUNTIME_FUNCTION(Runtime_ThrowNotDateError) {
HandleScope scope(isolate);
DCHECK(args.length() == 0);
- return isolate->Throw(*isolate->factory()->NewTypeError(
- "not_date_object", HandleVector<Object>(NULL, 0)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError("not_date_object", HandleVector<Object>(NULL, 0)));
}
bool result;
String::FlatContent str_content = str->GetFlatContent();
- if (str_content.IsAscii()) {
+ if (str_content.IsOneByte()) {
result = DateParser::Parse(str_content.ToOneByteVector(),
*output_array,
isolate->unicode_cache());
CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
source = String::Flatten(source);
- // Optimized fast case where we only have ASCII characters.
+ // Optimized fast case where we only have Latin1 characters.
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
}
-// 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);
DCHECK(args.length() == 2);
// Extract native context.
Handle<Context> context(isolate->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() &&
!CodeGenerationFromStringsAllowed(isolate, context)) {
Handle<Object> error_message =
context->ErrorMessageForCodeGenerationFromStrings();
- return isolate->Throw(*isolate->factory()->NewEvalError(
- "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewEvalError("code_gen_from_strings",
+ HandleVector<Object>(&error_message, 1)));
}
// Compile source string in the native context.
ParseRestriction restriction = function_literal_only
? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
+ Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
Handle<JSFunction> fun;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, fun,
Compiler::GetFunctionFromEval(
- source, context, SLOPPY, restriction, RelocInfo::kNoPosition));
+ source, outer_info,
+ context, SLOPPY, restriction, RelocInfo::kNoPosition));
return *fun;
}
static ObjectPair CompileGlobalEval(Isolate* isolate,
Handle<String> source,
+ Handle<SharedFunctionInfo> outer_info,
Handle<Object> receiver,
StrictMode strict_mode,
int scope_position) {
!CodeGenerationFromStringsAllowed(isolate, native_context)) {
Handle<Object> error_message =
native_context->ErrorMessageForCodeGenerationFromStrings();
- isolate->Throw(*isolate->factory()->NewEvalError(
- "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
+ Handle<Object> error;
+ MaybeHandle<Object> maybe_error = isolate->factory()->NewEvalError(
+ "code_gen_from_strings", HandleVector<Object>(&error_message, 1));
+ if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
return MakePair(isolate->heap()->exception(), NULL);
}
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, compiled,
Compiler::GetFunctionFromEval(
- source, context, strict_mode, restriction, scope_position),
+ source, outer_info,
+ context, strict_mode, restriction, scope_position),
MakePair(isolate->heap()->exception(), NULL));
return MakePair(*compiled, *receiver);
}
RUNTIME_FUNCTION_RETURN_PAIR(Runtime_ResolvePossiblyDirectEval) {
HandleScope scope(isolate);
- DCHECK(args.length() == 5);
+ DCHECK(args.length() == 6);
Handle<Object> callee = args.at<Object>(0);
return MakePair(*callee, isolate->heap()->undefined_value());
}
- DCHECK(args[3]->IsSmi());
- DCHECK(args.smi_at(3) == SLOPPY || args.smi_at(3) == STRICT);
- StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(3));
DCHECK(args[4]->IsSmi());
+ DCHECK(args.smi_at(4) == SLOPPY || args.smi_at(4) == STRICT);
+ StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(4));
+ DCHECK(args[5]->IsSmi());
+ Handle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
+ isolate);
return CompileGlobalEval(isolate,
args.at<String>(1),
- args.at<Object>(2),
+ outer_info,
+ args.at<Object>(3),
strict_mode,
- args.smi_at(4));
+ args.smi_at(5));
}
}
+static void IterateExternalFloat32x4ArrayElements(Isolate* isolate,
+ Handle<JSObject> receiver,
+ ArrayConcatVisitor* visitor) {
+ Handle<ExternalFloat32x4Array> array(
+ ExternalFloat32x4Array::cast(receiver->elements()));
+ uint32_t len = static_cast<uint32_t>(array->length());
+
+ DCHECK(visitor != NULL);
+ for (uint32_t j = 0; j < len; j++) {
+ HandleScope loop_scope(isolate);
+ Handle<Object> e = isolate->factory()->NewFloat32x4(array->get_scalar(j));
+ visitor->visit(j, e);
+ }
+}
+
+
+static void IterateExternalFloat64x2ArrayElements(Isolate* isolate,
+ Handle<JSObject> receiver,
+ ArrayConcatVisitor* visitor) {
+ Handle<ExternalFloat64x2Array> array(
+ ExternalFloat64x2Array::cast(receiver->elements()));
+ uint32_t len = static_cast<uint32_t>(array->length());
+
+ DCHECK(visitor != NULL);
+ for (uint32_t j = 0; j < len; j++) {
+ HandleScope loop_scope(isolate);
+ Handle<Object> e = isolate->factory()->NewFloat64x2(array->get_scalar(j));
+ visitor->visit(j, e);
+ }
+}
+
+
+static void IterateExternalInt32x4ArrayElements(Isolate* isolate,
+ Handle<JSObject> receiver,
+ ArrayConcatVisitor* visitor) {
+ Handle<ExternalInt32x4Array> array(
+ ExternalInt32x4Array::cast(receiver->elements()));
+ uint32_t len = static_cast<uint32_t>(array->length());
+
+ DCHECK(visitor != NULL);
+ for (uint32_t j = 0; j < len; j++) {
+ HandleScope loop_scope(isolate);
+ Handle<Object> e = isolate->factory()->NewInt32x4(array->get_scalar(j));
+ visitor->visit(j, e);
+ }
+}
+
+
// Used for sorting indices in a List<uint32_t>.
static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
uint32_t a = *ap;
}
case FAST_HOLEY_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS: {
- // TODO(1810): Decide if it's worthwhile to implement this.
- UNREACHABLE();
+ if (object->elements()->IsFixedArray()) {
+ DCHECK(object->elements()->length() == 0);
+ break;
+ }
+ Handle<FixedDoubleArray> elements(
+ FixedDoubleArray::cast(object->elements()));
+ uint32_t length = static_cast<uint32_t>(elements->length());
+ if (range < length) length = range;
+ for (uint32_t i = 0; i < length; i++) {
+ if (!elements->is_the_hole(i)) {
+ indices->Add(i);
+ }
+ }
break;
}
case DICTIONARY_ELEMENTS: {
}
break;
}
- default: {
- int dense_elements_length;
- switch (kind) {
-#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
- case EXTERNAL_##TYPE##_ELEMENTS: { \
- dense_elements_length = \
- External##Type##Array::cast(object->elements())->length(); \
- break; \
- }
+#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+ case TYPE##_ELEMENTS: \
+ case EXTERNAL_##TYPE##_ELEMENTS:
- TYPED_ARRAYS(TYPED_ARRAY_CASE)
+ TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
-
- default:
- UNREACHABLE();
- dense_elements_length = 0;
- break;
- }
- uint32_t length = static_cast<uint32_t>(dense_elements_length);
+ {
+ uint32_t length = static_cast<uint32_t>(
+ FixedArrayBase::cast(object->elements())->length());
if (range <= length) {
length = range;
// We will add all indices, so we might as well clear it first
if (length == range) return; // All indices accounted for already.
break;
}
+ case SLOPPY_ARGUMENTS_ELEMENTS: {
+ MaybeHandle<Object> length_obj =
+ Object::GetProperty(object, isolate->factory()->length_string());
+ double length_num = length_obj.ToHandleChecked()->Number();
+ uint32_t length = static_cast<uint32_t>(DoubleToInt32(length_num));
+ ElementsAccessor* accessor = object->GetElementsAccessor();
+ for (uint32_t i = 0; i < length; i++) {
+ if (accessor->HasElement(object, object, i)) {
+ indices->Add(i);
+ }
+ }
+ break;
+ }
}
PrototypeIterator iter(isolate, object);
isolate, receiver, false, false, visitor);
break;
}
+ case EXTERNAL_FLOAT32x4_ELEMENTS: {
+ IterateExternalFloat32x4ArrayElements(isolate, receiver, visitor);
+ break;
+ }
+ case EXTERNAL_FLOAT64x2_ELEMENTS: {
+ IterateExternalFloat64x2ArrayElements(isolate, receiver, visitor);
+ break;
+ }
+ case EXTERNAL_INT32x4_ELEMENTS: {
+ IterateExternalInt32x4ArrayElements(isolate, receiver, visitor);
+ break;
+ }
case EXTERNAL_FLOAT64_ELEMENTS: {
IterateExternalArrayElements<ExternalFloat64Array, double>(
isolate, receiver, false, false, visitor);
Handle<FixedArrayBase> storage =
isolate->factory()->NewFixedDoubleArray(estimate_result_length);
int j = 0;
+ bool failure = false;
if (estimate_result_length > 0) {
Handle<FixedDoubleArray> double_storage =
Handle<FixedDoubleArray>::cast(storage);
- bool failure = false;
for (int i = 0; i < argument_count; i++) {
Handle<Object> obj(elements->get(i), isolate);
if (obj->IsSmi()) {
FixedDoubleArray::cast(array->elements());
for (uint32_t i = 0; i < length; i++) {
if (elements->is_the_hole(i)) {
+ // TODO(jkummerow/verwaest): We could be a bit more clever
+ // here: Check if there are no elements/getters on the
+ // prototype chain, and if so, allow creation of a holey
+ // result array.
+ // Same thing below (holey smi case).
failure = true;
break;
}
break;
}
case FAST_HOLEY_ELEMENTS:
+ case FAST_ELEMENTS:
DCHECK_EQ(0, length);
break;
default:
if (failure) break;
}
}
- 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;
+ if (!failure) {
+ 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;
+ }
+ // In case of failure, fall through.
}
Handle<FixedArray> storage;
}
if (visitor.exceeds_array_limit()) {
- return isolate->Throw(
- *isolate->factory()->NewRangeError("invalid_array_length",
- HandleVector<Object>(NULL, 0)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate,
+ NewRangeError("invalid_array_length", HandleVector<Object>(NULL, 0)));
}
return *visitor.ToArray();
}
}
-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:
- return JSObject::GetNormalizedProperty(handle(result->holder(), isolate),
- result);
- case FIELD:
- return JSObject::FastPropertyAt(handle(result->holder(), isolate),
- result->representation(),
- result->GetFieldIndex());
- case CONSTANT:
- return handle(result->GetConstant(), isolate);
- case CALLBACKS: {
- Handle<Object> structure(result->GetCallbackObject(), isolate);
- DCHECK(!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();
+static Handle<Object> DebugGetProperty(LookupIterator* it,
+ bool* has_caught = NULL) {
+ for (; it->IsFound(); it->Next()) {
+ switch (it->state()) {
+ case LookupIterator::NOT_FOUND:
+ case LookupIterator::TRANSITION:
+ UNREACHABLE();
+ case LookupIterator::ACCESS_CHECK:
+ // Ignore access checks.
+ break;
+ case LookupIterator::INTERCEPTOR:
+ case LookupIterator::JSPROXY:
+ return it->isolate()->factory()->undefined_value();
+ case LookupIterator::ACCESSOR: {
+ Handle<Object> accessors = it->GetAccessors();
+ if (!accessors->IsAccessorInfo()) {
+ return it->isolate()->factory()->undefined_value();
+ }
+ MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithAccessor(
+ it->GetReceiver(), it->name(), it->GetHolder<JSObject>(),
+ accessors);
+ Handle<Object> result;
+ if (!maybe_result.ToHandle(&result)) {
+ result = handle(it->isolate()->pending_exception(), it->isolate());
+ it->isolate()->clear_pending_exception();
if (has_caught != NULL) *has_caught = true;
- return value;
}
+ return result;
}
- break;
+
+ case LookupIterator::DATA:
+ return it->GetDataValue();
}
- case INTERCEPTOR:
- case HANDLER:
- break;
- case NONEXISTENT:
- UNREACHABLE();
- break;
}
- return value;
+
+ return it->isolate()->factory()->undefined_value();
}
-// Get debugger related details for an object property.
-// args[0]: object holding property
-// args[1]: name of the property
-//
-// The array returned contains the following information:
+// Get debugger related details for an object property, in the following format:
// 0: Property value
// 1: Property details
// 2: Property value is exception
// 3: Getter function if defined
// 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__.
+// Items 2-4 are only filled if the property has either a getter or a setter.
RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
HandleScope scope(isolate);
return *isolate->factory()->NewJSArrayWithElements(details);
}
- // Find the number of objects making up this.
- int length = OwnPrototypeChainLength(*obj);
-
- // Try own lookup on each of the objects.
- PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
- for (int i = 0; i < length; i++) {
- DCHECK(!iter.IsAtEnd());
- Handle<JSObject> jsproto =
- Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
- LookupResult result(isolate);
- 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
- // local variables using handles when required for later use.
- Handle<Object> result_callback_obj;
- if (result.IsPropertyCallbacks()) {
- result_callback_obj = Handle<Object>(result.GetCallbackObject(),
- isolate);
- }
-
+ LookupIterator it(obj, name, LookupIterator::HIDDEN);
+ bool has_caught = false;
+ Handle<Object> value = DebugGetProperty(&it, &has_caught);
+ if (!it.IsFound()) return isolate->heap()->undefined_value();
- 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 has_js_accessors = result.IsPropertyCallbacks() &&
- result_callback_obj->IsAccessorPair();
- Handle<FixedArray> details =
- isolate->factory()->NewFixedArray(has_js_accessors ? 5 : 2);
- details->set(0, *value);
- details->set(1, result.GetPropertyDetails().AsSmi());
- if (has_js_accessors) {
- AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
- details->set(2, isolate->heap()->ToBoolean(has_caught));
- details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
- details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
- }
+ Handle<Object> maybe_pair;
+ if (it.state() == LookupIterator::ACCESSOR) {
+ maybe_pair = it.GetAccessors();
+ }
- return *isolate->factory()->NewJSArrayWithElements(details);
- }
- iter.Advance();
+ // If the callback object is a fixed array then it contains JavaScript
+ // getter and/or setter.
+ bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
+ Handle<FixedArray> details =
+ isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
+ details->set(0, *value);
+ // TODO(verwaest): Get rid of this random way of handling interceptors.
+ PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
+ ? PropertyDetails(NONE, NORMAL, 0)
+ : it.property_details();
+ details->set(1, d.AsSmi());
+ details->set(
+ 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
+ if (has_js_accessors) {
+ AccessorPair* accessors = AccessorPair::cast(*maybe_pair);
+ details->set(3, isolate->heap()->ToBoolean(has_caught));
+ details->set(4, accessors->GetComponent(ACCESSOR_GETTER));
+ details->set(5, accessors->GetComponent(ACCESSOR_SETTER));
}
- return isolate->heap()->undefined_value();
+ return *isolate->factory()->NewJSArrayWithElements(details);
}
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
- LookupResult result(isolate);
- obj->Lookup(name, &result);
- return *DebugLookupResultValue(isolate, obj, name, &result);
+ LookupIterator it(obj, name);
+ return *DebugGetProperty(&it);
}
? deoptimized_frame_->HasConstructStub()
: frame_->IsConstructor();
}
+ Object* GetContext() {
+ return is_optimized_ ? deoptimized_frame_->GetContext() : frame_->context();
+ }
// To inspect all the provided arguments the frame might need to be
// replaced with the arguments frame.
}
-RUNTIME_FUNCTION(Runtime_IsOptimized) {
- SealHandleScope shs(isolate);
- DCHECK(args.length() == 0);
- JavaScriptFrameIterator it(isolate);
- JavaScriptFrame* frame = it.frame();
- return isolate->heap()->ToBoolean(frame->is_optimized());
-}
-
-
// Advances the iterator to the frame that matches the index and returns the
// inlined frame index, or -1 if not found. Skips native JS functions.
static int FindIndexedNonNativeFrame(JavaScriptFrameIterator* it, int index) {
if (local < local_count) {
// Get the context containing declarations.
Handle<Context> context(
- Context::cast(it.frame()->context())->declaration_context());
+ Context::cast(frame_inspector.GetContext())->declaration_context());
for (; i < scope_info->LocalCount(); ++i) {
if (scope_info->LocalIsSynthetic(i))
continue;
if (receiver->IsUndefined()) {
receiver = handle(function->global_proxy());
} else {
- DCHECK(!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();
+ if (!Object::ToObject(isolate, receiver, native_context)
+ .ToHandle(&receiver)) {
+ // This only happens if the receiver is forcibly set in %_CallFunction.
+ return heap->undefined_value();
+ }
}
}
details->set(kFrameDetailsReceiverIndex, *receiver);
// Compile and evaluate source for the given context.
static MaybeHandle<Object> DebugEvaluate(Isolate* isolate,
+ Handle<SharedFunctionInfo> outer_info,
Handle<Context> context,
Handle<Object> context_extension,
Handle<Object> receiver,
ASSIGN_RETURN_ON_EXCEPTION(
isolate, eval_fun,
Compiler::GetFunctionFromEval(source,
+ outer_info,
context,
SLOPPY,
NO_PARSE_RESTRICTION,
}
+static Handle<JSObject> NewJSObjectWithNullProto(Isolate* isolate) {
+ Handle<JSObject> result =
+ isolate->factory()->NewJSObject(isolate->object_function());
+ Handle<Map> new_map = Map::Copy(Handle<Map>(result->map()));
+ new_map->set_prototype(*isolate->factory()->null_value());
+ JSObject::MigrateToMap(result, new_map);
+ return result;
+}
+
+
// Evaluate a piece of JavaScript in the context of a stack frame for
// debugging. Things that need special attention are:
// - Parameters and stack-allocated locals need to be materialized. Altered
JavaScriptFrame* frame = it.frame();
FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
+ Handle<SharedFunctionInfo> outer_info(function->shared());
// Traverse the saved contexts chain to find the active context for the
// selected frame.
isolate->set_context(*(save->context()));
// Evaluate on the context of the frame.
- Handle<Context> context(Context::cast(frame->context()));
+ Handle<Context> context(Context::cast(frame_inspector.GetContext()));
DCHECK(!context.is_null());
// Materialize stack locals and the arguments object.
- Handle<JSObject> materialized =
- isolate->factory()->NewJSObject(isolate->object_function());
+ Handle<JSObject> materialized = NewJSObjectWithNullProto(isolate);
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, materialized,
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
- DebugEvaluate(isolate, context, context_extension, receiver, source));
+ DebugEvaluate(isolate, outer_info,
+ context, context_extension, receiver, source));
// Write back potential changes to materialized stack locals to the stack.
UpdateStackLocalsFromMaterializedObject(
// debugger was invoked.
Handle<Context> context = isolate->native_context();
Handle<JSObject> receiver(context->global_proxy());
+ Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
- DebugEvaluate(isolate, context, context_extension, receiver, source));
+ DebugEvaluate(isolate, outer_info,
+ context, context_extension, receiver, source));
return *result;
}
return *factory->NewStringFromAsciiChecked(result);
}
- return *factory->NewStringFromStaticAscii("und");
+ return *factory->NewStringFromStaticChars("und");
}
// 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");
+ Handle<Name> maximized = factory->NewStringFromStaticChars("maximized");
+ Handle<Name> base = factory->NewStringFromStaticChars("base");
for (unsigned int i = 0; i < length; ++i) {
Handle<Object> locale_id;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
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);
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate,
+ NewTypeError("not_intl_object", arguments));
}
Handle<JSObject> obj = Handle<JSObject>::cast(input);
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);
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate,
+ NewTypeError("not_intl_object", arguments));
}
return *impl;
}
local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
Factory* factory = isolate->factory();
- Handle<String> key = factory->NewStringFromStaticAscii("dateFormat");
- Handle<String> value = factory->NewStringFromStaticAscii("valid");
+ Handle<String> key = factory->NewStringFromStaticChars("dateFormat");
+ Handle<String> value = factory->NewStringFromStaticChars("valid");
JSObject::AddProperty(local_object, key, value, NONE);
// Make object handle weak so we can delete the data format once GC kicks in.
local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
Factory* factory = isolate->factory();
- Handle<String> key = factory->NewStringFromStaticAscii("numberFormat");
- Handle<String> value = factory->NewStringFromStaticAscii("valid");
+ Handle<String> key = factory->NewStringFromStaticChars("numberFormat");
+ Handle<String> value = factory->NewStringFromStaticChars("valid");
JSObject::AddProperty(local_object, key, value, NONE);
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
Factory* factory = isolate->factory();
- Handle<String> key = factory->NewStringFromStaticAscii("collator");
- Handle<String> value = factory->NewStringFromStaticAscii("valid");
+ Handle<String> key = factory->NewStringFromStaticChars("collator");
+ Handle<String> value = factory->NewStringFromStaticChars("valid");
JSObject::AddProperty(local_object, key, value, NONE);
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
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));
+ static_cast<size_t>(form_id) < arraysize(normalizationForms));
v8::String::Value string_value(v8::Utils::ToLocal(stringValue));
const UChar* u_value = reinterpret_cast<const UChar*>(*string_value);
local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
Factory* factory = isolate->factory();
- Handle<String> key = factory->NewStringFromStaticAscii("breakIterator");
- Handle<String> value = factory->NewStringFromStaticAscii("valid");
+ Handle<String> key = factory->NewStringFromStaticChars("breakIterator");
+ Handle<String> value = factory->NewStringFromStaticChars("valid");
JSObject::AddProperty(local_object, key, value, NONE);
// Make object handle weak so we can delete the break iterator once GC kicks
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()->NewStringFromStaticAscii("none");
+ return *isolate->factory()->NewStringFromStaticChars("none");
} else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
- return *isolate->factory()->NewStringFromStaticAscii("number");
+ return *isolate->factory()->number_string();
} else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
- return *isolate->factory()->NewStringFromStaticAscii("letter");
+ return *isolate->factory()->NewStringFromStaticChars("letter");
} else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
- return *isolate->factory()->NewStringFromStaticAscii("kana");
+ return *isolate->factory()->NewStringFromStaticChars("kana");
} else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
- return *isolate->factory()->NewStringFromStaticAscii("ideo");
+ return *isolate->factory()->NewStringFromStaticChars("ideo");
} else {
- return *isolate->factory()->NewStringFromStaticAscii("unknown");
+ return *isolate->factory()->NewStringFromStaticChars("unknown");
}
}
#endif // V8_I18N_SUPPORT
}
+// Returns function of generator activation.
+RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
+
+ return generator->function();
+}
+
+
+// Returns context of generator activation.
+RUNTIME_FUNCTION(Runtime_GeneratorGetContext) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
+
+ return generator->context();
+}
+
+
+// Returns receiver of generator activation.
+RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
+
+ return generator->receiver();
+}
+
+
+// Returns generator continuation as a PC offset, or the magic -1 or 0 values.
+RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
+
+ return Smi::FromInt(generator->continuation());
+}
+
+
+RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
+
+ if (generator->is_suspended()) {
+ Handle<Code> code(generator->function()->code(), isolate);
+ int offset = generator->continuation();
+
+ RUNTIME_ASSERT(0 <= offset && offset < code->Size());
+ Address pc = code->address() + offset;
+
+ return Smi::FromInt(code->SourcePosition(pc));
+ }
+
+ return isolate->heap()->undefined_value();
+}
+
+
RUNTIME_FUNCTION(Runtime_Abort) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
Handle<Object> argv[] = { key_handle };
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, value,
- Execution::Call(isolate, factory, receiver, ARRAY_SIZE(argv), argv));
+ Execution::Call(isolate, factory, receiver, arraysize(argv), argv));
}
#ifdef VERIFY_HEAP
Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
int index = 0;
bool inline_runtime_functions = false;
-#define ADD_ENTRY(Name, argc, ressize) \
- { \
- HandleScope inner(isolate); \
- Handle<String> name; \
- /* Inline runtime functions have an underscore in front of the name. */ \
- if (inline_runtime_functions) { \
- name = factory->NewStringFromStaticAscii("_" #Name); \
- } else { \
- name = factory->NewStringFromStaticAscii(#Name); \
- } \
- Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \
- pair_elements->set(0, *name); \
- pair_elements->set(1, Smi::FromInt(argc)); \
- Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements); \
- elements->set(index++, *pair); \
+#define ADD_ENTRY(Name, argc, ressize) \
+ { \
+ HandleScope inner(isolate); \
+ Handle<String> name; \
+ /* Inline runtime functions have an underscore in front of the name. */ \
+ if (inline_runtime_functions) { \
+ name = factory->NewStringFromStaticChars("_" #Name); \
+ } else { \
+ name = factory->NewStringFromStaticChars(#Name); \
+ } \
+ Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \
+ pair_elements->set(0, *name); \
+ pair_elements->set(1, Smi::FromInt(argc)); \
+ Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements); \
+ elements->set(index++, *pair); \
}
inline_runtime_functions = false;
RUNTIME_FUNCTION_LIST(ADD_ENTRY)
RUNTIME_FUNCTION_RETURN_PAIR(Runtime_ForInNext) {
SealHandleScope scope(isolate);
DCHECK(args.length() == 4);
+ int32_t index;
// This simulates CONVERT_ARG_HANDLE_CHECKED for calls returning pairs.
// Not worth creating a macro atm as this function should be removed.
if (!args[0]->IsJSReceiver() || !args[1]->IsFixedArray() ||
- !args[2]->IsObject() || !args[3]->IsSmi()) {
+ !args[2]->IsObject() || !args[3]->ToInt32(&index)) {
Object* error = isolate->ThrowIllegalOperation();
return MakePair(error, isolate->heap()->undefined_value());
}
Handle<JSReceiver> object = args.at<JSReceiver>(0);
Handle<FixedArray> array = args.at<FixedArray>(1);
Handle<Object> cache_type = args.at<Object>(2);
- int index = args.smi_at(3);
// Figure out first if a slow check is needed for this object.
bool slow_check_needed = false;
if (cache_type->IsMap()) {
}
+template<typename T, int Bytes>
+inline static bool SimdTypeLoadValue(
+ Isolate* isolate,
+ Handle<JSArrayBuffer> buffer,
+ Handle<Object> byte_offset_obj,
+ T* result) {
+ size_t byte_offset = 0;
+ if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
+ return false;
+ }
+
+ size_t buffer_byte_length =
+ NumberToSize(isolate, buffer->byte_length());
+ if (byte_offset + Bytes > buffer_byte_length) { // overflow
+ return false;
+ }
+
+ union Value {
+ T data;
+ uint8_t bytes[sizeof(T)];
+ };
+
+ Value value;
+ memset(value.bytes, 0, sizeof(T));
+ uint8_t* source =
+ static_cast<uint8_t*>(buffer->backing_store()) + byte_offset;
+ DCHECK(Bytes <= sizeof(T));
+ CopyBytes<Bytes>(value.bytes, source);
+ *result = value.data;
+ return true;
+}
+
+
+template<typename T, int Bytes>
+static bool SimdTypeStoreValue(
+ Isolate* isolate,
+ Handle<JSArrayBuffer> buffer,
+ Handle<Object> byte_offset_obj,
+ T data) {
+ size_t byte_offset = 0;
+ if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
+ return false;
+ }
+
+ size_t buffer_byte_length =
+ NumberToSize(isolate, buffer->byte_length());
+ if (byte_offset + Bytes > buffer_byte_length) { // overflow
+ return false;
+ }
+
+ union Value {
+ T data;
+ uint8_t bytes[sizeof(T)];
+ };
+
+ Value value;
+ value.data = data;
+
+ uint8_t* target =
+ static_cast<uint8_t*>(buffer->backing_store()) + byte_offset;
+ DCHECK(Bytes <= sizeof(T));
+ CopyBytes<Bytes>(target, value.bytes);
+ return true;
+}
+
+
+#define SIMD128_LOAD_RUNTIME_FUNCTION(Type, ValueType, Lanes, Bytes) \
+RUNTIME_FUNCTION(Runtime_##Type##Load##Lanes) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 2); \
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0); \
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \
+ ValueType result; \
+ if (SimdTypeLoadValue<ValueType, Bytes>( \
+ isolate, buffer, offset, &result)) { \
+ return *isolate->factory()->New##Type(result); \
+ } else { \
+ THROW_NEW_ERROR_RETURN_FAILURE( \
+ isolate, NewRangeError("invalid_offset", \
+ HandleVector<Object>(NULL, 0))); \
+ } \
+}
+
+
+SIMD128_LOAD_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XYZW, 16)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XYZ, 12)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XY, 8)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, X, 4)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float64x2, float64x2_value_t, XY, 16)
+SIMD128_LOAD_RUNTIME_FUNCTION(Float64x2, float64x2_value_t, X, 8)
+SIMD128_LOAD_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XYZW, 16)
+SIMD128_LOAD_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XYZ, 12)
+SIMD128_LOAD_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XY, 8)
+SIMD128_LOAD_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, X, 4)
+
+
+#define SIMD128_STORE_RUNTIME_FUNCTION(Type, ValueType, Lanes, Bytes) \
+RUNTIME_FUNCTION(Runtime_##Type##Store##Lanes) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 3); \
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0); \
+ CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \
+ CONVERT_ARG_CHECKED(Type, value, 2); \
+ ValueType v = value->get(); \
+ if (SimdTypeStoreValue<ValueType, Bytes>(isolate, buffer, offset, v)) { \
+ return isolate->heap()->undefined_value(); \
+ } else { \
+ THROW_NEW_ERROR_RETURN_FAILURE( \
+ isolate, NewRangeError("invalid_offset", \
+ HandleVector<Object>(NULL, 0))); \
+ } \
+}
+
+
+SIMD128_STORE_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XYZW, 16)
+SIMD128_STORE_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XYZ, 12)
+SIMD128_STORE_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, XY, 8)
+SIMD128_STORE_RUNTIME_FUNCTION(Float32x4, float32x4_value_t, X, 4)
+SIMD128_STORE_RUNTIME_FUNCTION(Float64x2, float64x2_value_t, XY, 16)
+SIMD128_STORE_RUNTIME_FUNCTION(Float64x2, float64x2_value_t, X, 8)
+SIMD128_STORE_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XYZW, 16)
+SIMD128_STORE_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XYZ, 12)
+SIMD128_STORE_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, XY, 8)
+SIMD128_STORE_RUNTIME_FUNCTION(Int32x4, int32x4_value_t, X, 4)
+
+
+#define RETURN_Float32x4_RESULT(value) \
+ return *isolate->factory()->NewFloat32x4(value);
+
+
+#define RETURN_Float64x2_RESULT(value) \
+ return *isolate->factory()->NewFloat64x2(value);
+
+
+#define RETURN_Int32x4_RESULT(value) \
+ return *isolate->factory()->NewInt32x4(value);
+
+
+RUNTIME_FUNCTION(Runtime_CreateFloat32x4) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 4);
+ RUNTIME_ASSERT(args[0]->IsNumber());
+ RUNTIME_ASSERT(args[1]->IsNumber());
+ RUNTIME_ASSERT(args[2]->IsNumber());
+ RUNTIME_ASSERT(args[3]->IsNumber());
+
+ float32x4_value_t value;
+ value.storage[0] = static_cast<float>(args.number_at(0));
+ value.storage[1] = static_cast<float>(args.number_at(1));
+ value.storage[2] = static_cast<float>(args.number_at(2));
+ value.storage[3] = static_cast<float>(args.number_at(3));
+
+ RETURN_Float32x4_RESULT(value);
+}
+
+
+RUNTIME_FUNCTION(Runtime_CreateFloat64x2) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 2);
+ RUNTIME_ASSERT(args[0]->IsNumber());
+ RUNTIME_ASSERT(args[1]->IsNumber());
+
+ float64x2_value_t value;
+ value.storage[0] = args.number_at(0);
+ value.storage[1] = args.number_at(1);
+
+ RETURN_Float64x2_RESULT(value);
+}
+
+
+RUNTIME_FUNCTION(Runtime_CreateInt32x4) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 4);
+ RUNTIME_ASSERT(args[0]->IsNumber());
+ RUNTIME_ASSERT(args[1]->IsNumber());
+ RUNTIME_ASSERT(args[2]->IsNumber());
+ RUNTIME_ASSERT(args[3]->IsNumber());
+
+ int32x4_value_t value;
+ value.storage[0] = NumberToInt32(args[0]);
+ value.storage[1] = NumberToInt32(args[1]);
+ value.storage[2] = NumberToInt32(args[2]);
+ value.storage[3] = NumberToInt32(args[3]);
+
+ RETURN_Int32x4_RESULT(value);
+}
+
+
+// Used to convert between uint32_t and float32 without breaking strict
+// aliasing rules.
+union float32_uint32 {
+ float f;
+ uint32_t u;
+ float32_uint32(float v) {
+ f = v;
+ }
+ float32_uint32(uint32_t v) {
+ u = v;
+ }
+};
+
+
+union float64_uint64 {
+ double f;
+ uint64_t u;
+ float64_uint64(double v) {
+ f = v;
+ }
+ float64_uint64(uint64_t v) {
+ u = v;
+ }
+};
+
+
+RUNTIME_FUNCTION(Runtime_Float32x4GetSignMask) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_CHECKED(Float32x4, self, 0);
+ float32_uint32 x(self->x());
+ float32_uint32 y(self->y());
+ float32_uint32 z(self->z());
+ float32_uint32 w(self->w());
+ uint32_t mx = (x.u & 0x80000000) >> 31;
+ uint32_t my = (y.u & 0x80000000) >> 31;
+ uint32_t mz = (z.u & 0x80000000) >> 31;
+ uint32_t mw = (w.u & 0x80000000) >> 31;
+ uint32_t value = mx | (my << 1) | (mz << 2) | (mw << 3);
+ return *isolate->factory()->NewNumberFromUint(value);
+}
+
+
+RUNTIME_FUNCTION(Runtime_Float64x2GetSignMask) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_CHECKED(Float64x2, self, 0);
+ float64_uint64 x(self->x());
+ float64_uint64 y(self->y());
+ uint64_t mx = x.u >> 63;
+ uint64_t my = y.u >> 63;
+ uint32_t value = uint32_t(mx | (my << 1));
+ return *isolate->factory()->NewNumberFromUint(value);
+}
+
+
+RUNTIME_FUNCTION(Runtime_Int32x4GetSignMask) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_CHECKED(Int32x4, self, 0);
+ uint32_t mx = (self->x() & 0x80000000) >> 31;
+ uint32_t my = (self->y() & 0x80000000) >> 31;
+ uint32_t mz = (self->z() & 0x80000000) >> 31;
+ uint32_t mw = (self->w() & 0x80000000) >> 31;
+ uint32_t value = mx | (my << 1) | (mz << 2) | (mw << 3);
+ return *isolate->factory()->NewNumberFromUint(value);
+}
+
+
+#define LANE_VALUE(VALUE, LANE) \
+ VALUE->LANE()
+
+
+#define LANE_FLAG(VALUE, LANE) \
+ VALUE->LANE() != 0
+
+
+#define SIMD128_LANE_ACCESS_FUNCTIONS(V) \
+ V(Float32x4, GetX, NewNumber, x, LANE_VALUE) \
+ V(Float32x4, GetY, NewNumber, y, LANE_VALUE) \
+ V(Float32x4, GetZ, NewNumber, z, LANE_VALUE) \
+ V(Float32x4, GetW, NewNumber, w, LANE_VALUE) \
+ V(Float64x2, GetX, NewNumber, x, LANE_VALUE) \
+ V(Float64x2, GetY, NewNumber, y, LANE_VALUE) \
+ V(Int32x4, GetX, NewNumberFromInt, x, LANE_VALUE) \
+ V(Int32x4, GetY, NewNumberFromInt, y, LANE_VALUE) \
+ V(Int32x4, GetZ, NewNumberFromInt, z, LANE_VALUE) \
+ V(Int32x4, GetW, NewNumberFromInt, w, LANE_VALUE) \
+ V(Int32x4, GetFlagX, ToBoolean, x, LANE_FLAG) \
+ V(Int32x4, GetFlagY, ToBoolean, y, LANE_FLAG) \
+ V(Int32x4, GetFlagZ, ToBoolean, z, LANE_FLAG) \
+ V(Int32x4, GetFlagW, ToBoolean, w, LANE_FLAG)
+
+
+#define DECLARE_SIMD_LANE_ACCESS_FUNCTION( \
+ TYPE, NAME, HEAP_FUNCTION, LANE, ACCESS_FUNCTION) \
+RUNTIME_FUNCTION(Runtime_##TYPE##NAME) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 1); \
+ \
+ CONVERT_ARG_CHECKED(TYPE, a, 0); \
+ \
+ return *isolate->factory()->HEAP_FUNCTION( \
+ ACCESS_FUNCTION(a, LANE)); \
+}
+
+
+SIMD128_LANE_ACCESS_FUNCTIONS(DECLARE_SIMD_LANE_ACCESS_FUNCTION)
+
+
+template<typename T>
+static inline T Neg(T a) {
+ return -a;
+}
+
+
+template<typename T>
+static inline T Not(T a) {
+ return ~a;
+}
+
+
+template<typename T>
+static inline T Reciprocal(T a) {
+ UNIMPLEMENTED();
+}
+
+
+template<>
+inline float Reciprocal<float>(float a) {
+ return 1.0f / a;
+}
+
+
+template<typename T>
+static inline T ReciprocalSqrt(T a) {
+ UNIMPLEMENTED();
+}
+
+
+template<>
+inline float ReciprocalSqrt<float>(float a) {
+ return sqrtf(1.0f / a);
+}
+
+
+template<typename T>
+static inline T Sqrt(T a) {
+ UNIMPLEMENTED();
+}
+
+
+template<>
+inline float Sqrt<float>(float a) {
+ return sqrtf(a);
+}
+
+
+template<>
+inline double Sqrt<double>(double a) {
+ return sqrt(a);
+}
+
+
+#define SIMD128_UNARY_FUNCTIONS(V) \
+ V(Float32x4, Abs) \
+ V(Float32x4, Neg) \
+ V(Float32x4, Reciprocal) \
+ V(Float32x4, ReciprocalSqrt) \
+ V(Float32x4, Sqrt) \
+ V(Float64x2, Abs) \
+ V(Float64x2, Neg) \
+ V(Float64x2, Sqrt) \
+ V(Int32x4, Neg) \
+ V(Int32x4, Not)
+
+
+#define DECLARE_SIMD_UNARY_FUNCTION(TYPE, FUNCTION) \
+RUNTIME_FUNCTION(Runtime_##TYPE##FUNCTION) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 1); \
+ \
+ CONVERT_ARG_CHECKED(TYPE, a, 0); \
+ \
+ TYPE::value_t result; \
+ for (int i = 0; i < TYPE::kLanes; i++) { \
+ result.storage[i] = FUNCTION(a->getAt(i)); \
+ } \
+ \
+ RETURN_##TYPE##_RESULT(result); \
+}
+
+
+SIMD128_UNARY_FUNCTIONS(DECLARE_SIMD_UNARY_FUNCTION)
+
+
+template<typename T1, typename T2>
+inline void BitsTo(T1 s, T2* t) {
+ memcpy(t, &s, sizeof(T2));
+}
+
+
+template<typename T1, typename T2>
+inline void To(T1 s, T2* t) {
+}
+
+
+template<>
+inline void To<int32_t, float>(int32_t s, float* t) {
+ *t = static_cast<float>(s);
+}
+
+
+template<>
+inline void To<float, int32_t>(float s, int32_t* t) {
+ *t = DoubleToInt32(static_cast<double>(s));
+}
+
+
+#define SIMD128_CONVERSION_FUNCTIONS(V) \
+ V(Float32x4, BitsTo, Int32x4) \
+ V(Float32x4, To, Int32x4) \
+ V(Int32x4, BitsTo, Float32x4) \
+ V(Int32x4, To, Float32x4)
+
+
+#define DECLARE_SIMD_CONVERSION_FUNCTION( \
+ SOURCE_TYPE, FUNCTION, TARGET_TYPE) \
+RUNTIME_FUNCTION( \
+ Runtime_##SOURCE_TYPE##FUNCTION##TARGET_TYPE) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 1); \
+ \
+ CONVERT_ARG_CHECKED(SOURCE_TYPE, a, 0); \
+ \
+ TARGET_TYPE::value_t result; \
+ for (int i = 0; i < SOURCE_TYPE::kLanes; i++) { \
+ FUNCTION(a->getAt(i), &result.storage[i]); \
+ } \
+ \
+ RETURN_##TARGET_TYPE##_RESULT(result); \
+}
+
+
+SIMD128_CONVERSION_FUNCTIONS(DECLARE_SIMD_CONVERSION_FUNCTION)
+
+
+template<typename T>
+static inline T Add(T a, T b) {
+ return a + b;
+}
+
+
+template<typename T>
+static inline T Div(T a, T b) {
+ return a / b;
+}
+
+
+template<typename T>
+static inline T Mul(T a, T b) {
+ return a * b;
+}
+
+
+template<typename T>
+static inline T Sub(T a, T b) {
+ return a - b;
+}
+
+
+template<typename T>
+static inline int32_t Equal(T a, T b) {
+ return a == b ? -1 : 0;
+}
+
+
+template<typename T>
+static inline int32_t NotEqual(T a, T b) {
+ return a != b ? -1 : 0;
+}
+
+
+template<typename T>
+static inline int32_t GreaterThanOrEqual(T a, T b) {
+ return a >= b ? -1 : 0;
+}
+
+
+template<typename T>
+static inline int32_t GreaterThan(T a, T b) {
+ return a > b ? -1 : 0;
+}
+
+
+template<typename T>
+static inline int32_t LessThan(T a, T b) {
+ return a < b ? -1 : 0;
+}
+
+
+template<typename T>
+static inline int32_t LessThanOrEqual(T a, T b) {
+ return a <= b ? -1 : 0;
+}
+
+
+template<typename T>
+static inline T And(T a, T b) {
+ return a & b;
+}
+
+
+template<typename T>
+static inline T Or(T a, T b) {
+ return a | b;
+}
+
+
+template<typename T>
+static inline T Xor(T a, T b) {
+ return a ^ b;
+}
+
+
+#define SIMD128_BINARY_FUNCTIONS(V) \
+ V(Float32x4, Add, Float32x4) \
+ V(Float32x4, Div, Float32x4) \
+ V(Float32x4, Max, Float32x4) \
+ V(Float32x4, Min, Float32x4) \
+ V(Float32x4, Mul, Float32x4) \
+ V(Float32x4, Sub, Float32x4) \
+ V(Float32x4, Equal, Int32x4) \
+ V(Float32x4, NotEqual, Int32x4) \
+ V(Float32x4, GreaterThanOrEqual, Int32x4) \
+ V(Float32x4, GreaterThan, Int32x4) \
+ V(Float32x4, LessThan, Int32x4) \
+ V(Float32x4, LessThanOrEqual, Int32x4) \
+ V(Float64x2, Add, Float64x2) \
+ V(Float64x2, Div, Float64x2) \
+ V(Float64x2, Max, Float64x2) \
+ V(Float64x2, Min, Float64x2) \
+ V(Float64x2, Mul, Float64x2) \
+ V(Float64x2, Sub, Float64x2) \
+ V(Int32x4, Add, Int32x4) \
+ V(Int32x4, And, Int32x4) \
+ V(Int32x4, Mul, Int32x4) \
+ V(Int32x4, Or, Int32x4) \
+ V(Int32x4, Sub, Int32x4) \
+ V(Int32x4, Xor, Int32x4) \
+ V(Int32x4, Equal, Int32x4) \
+ V(Int32x4, GreaterThan, Int32x4) \
+ V(Int32x4, LessThan, Int32x4)
+
+
+#define DECLARE_SIMD_BINARY_FUNCTION( \
+ TYPE, FUNCTION, RETURN_TYPE) \
+RUNTIME_FUNCTION(Runtime_##TYPE##FUNCTION) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 2); \
+ \
+ CONVERT_ARG_CHECKED(TYPE, a, 0); \
+ CONVERT_ARG_CHECKED(TYPE, b, 1); \
+ \
+ RETURN_TYPE::value_t result; \
+ for (int i = 0; i < TYPE::kLanes; i++) { \
+ result.storage[i] = FUNCTION(a->getAt(i), b->getAt(i)); \
+ } \
+ \
+ RETURN_##RETURN_TYPE##_RESULT(result); \
+}
+
+
+SIMD128_BINARY_FUNCTIONS(DECLARE_SIMD_BINARY_FUNCTION)
+
+
+#define SIMD128_SHUFFLE_FUNCTIONS(V) \
+ V(Float32x4) \
+ V(Int32x4)
+
+
+#define DECLARE_SIMD_SHUFFLE_FUNCTION(TYPE) \
+RUNTIME_FUNCTION(Runtime_##TYPE##Shuffle) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 2); \
+ \
+ CONVERT_ARG_CHECKED(TYPE, a, 0); \
+ RUNTIME_ASSERT(args[1]->IsNumber()); \
+ uint32_t m = NumberToUint32(args[1]); \
+ \
+ TYPE::value_t result; \
+ for (int i = 0; i < TYPE::kLanes; i++) { \
+ result.storage[i] = a->getAt((m >> (i * 2)) & 0x3); \
+ } \
+ \
+ RETURN_##TYPE##_RESULT(result); \
+}
+
+
+SIMD128_SHUFFLE_FUNCTIONS(DECLARE_SIMD_SHUFFLE_FUNCTION)
+
+
+RUNTIME_FUNCTION(Runtime_Float32x4Scale) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 2);
+
+ CONVERT_ARG_CHECKED(Float32x4, self, 0);
+ RUNTIME_ASSERT(args[1]->IsNumber());
+
+ float _s = static_cast<float>(args.number_at(1));
+ float32x4_value_t result;
+ result.storage[0] = self->x() * _s;
+ result.storage[1] = self->y() * _s;
+ result.storage[2] = self->z() * _s;
+ result.storage[3] = self->w() * _s;
+
+ RETURN_Float32x4_RESULT(result);
+}
+
+
+RUNTIME_FUNCTION(Runtime_Float64x2Scale) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 2);
+
+ CONVERT_ARG_CHECKED(Float64x2, self, 0);
+ RUNTIME_ASSERT(args[1]->IsNumber());
+
+ double _s = args.number_at(1);
+ float64x2_value_t result;
+ result.storage[0] = self->x() * _s;
+ result.storage[1] = self->y() * _s;
+
+ RETURN_Float64x2_RESULT(result);
+}
+
+
+#define ARG_TO_FLOAT32(x) \
+ CONVERT_DOUBLE_ARG_CHECKED(t, 1); \
+ float x = static_cast<float>(t);
+
+
+#define ARG_TO_FLOAT64(x) \
+ CONVERT_DOUBLE_ARG_CHECKED(x, 1); \
+
+
+#define ARG_TO_INT32(x) \
+ RUNTIME_ASSERT(args[1]->IsNumber()); \
+ int32_t x = NumberToInt32(args[1]);
+
+
+#define ARG_TO_BOOLEAN(x) \
+ CONVERT_BOOLEAN_ARG_CHECKED(flag, 1); \
+ int32_t x = flag ? -1 : 0;
+
+#define SIMD128_SET_LANE_FUNCTIONS(V) \
+ V(Float32x4, WithX, ARG_TO_FLOAT32, 0) \
+ V(Float32x4, WithY, ARG_TO_FLOAT32, 1) \
+ V(Float32x4, WithZ, ARG_TO_FLOAT32, 2) \
+ V(Float32x4, WithW, ARG_TO_FLOAT32, 3) \
+ V(Float64x2, WithX, ARG_TO_FLOAT64, 0) \
+ V(Float64x2, WithY, ARG_TO_FLOAT64, 1) \
+ V(Int32x4, WithX, ARG_TO_INT32, 0) \
+ V(Int32x4, WithY, ARG_TO_INT32, 1) \
+ V(Int32x4, WithZ, ARG_TO_INT32, 2) \
+ V(Int32x4, WithW, ARG_TO_INT32, 3) \
+ V(Int32x4, WithFlagX, ARG_TO_BOOLEAN, 0) \
+ V(Int32x4, WithFlagY, ARG_TO_BOOLEAN, 1) \
+ V(Int32x4, WithFlagZ, ARG_TO_BOOLEAN, 2) \
+ V(Int32x4, WithFlagW, ARG_TO_BOOLEAN, 3)
+
+
+#define DECLARE_SIMD_SET_LANE_FUNCTION( \
+ TYPE, NAME, ARG_FUNCTION, LANE) \
+RUNTIME_FUNCTION(Runtime_##TYPE##NAME) { \
+ HandleScope scope(isolate); \
+ DCHECK(args.length() == 2); \
+ \
+ CONVERT_ARG_CHECKED(TYPE, a, 0); \
+ ARG_FUNCTION(value); \
+ \
+ TYPE::value_t result; \
+ for (int i = 0; i < TYPE::kLanes; i++) { \
+ if (i != LANE) \
+ result.storage[i] = a->getAt(i); \
+ else \
+ result.storage[i] = value; \
+ } \
+ \
+ RETURN_##TYPE##_RESULT(result); \
+}
+
+
+SIMD128_SET_LANE_FUNCTIONS(DECLARE_SIMD_SET_LANE_FUNCTION)
+
+
+RUNTIME_FUNCTION(Runtime_Float32x4Clamp) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 3);
+
+ CONVERT_ARG_CHECKED(Float32x4, self, 0);
+ CONVERT_ARG_CHECKED(Float32x4, lo, 1);
+ CONVERT_ARG_CHECKED(Float32x4, hi, 2);
+
+ float32x4_value_t result;
+ float _x = self->x() > lo->x() ? self->x() : lo->x();
+ float _y = self->y() > lo->y() ? self->y() : lo->y();
+ float _z = self->z() > lo->z() ? self->z() : lo->z();
+ float _w = self->w() > lo->w() ? self->w() : lo->w();
+ result.storage[0] = _x > hi->x() ? hi->x() : _x;
+ result.storage[1] = _y > hi->y() ? hi->y() : _y;
+ result.storage[2] = _z > hi->z() ? hi->z() : _z;
+ result.storage[3] = _w > hi->w() ? hi->w() : _w;
+
+ RETURN_Float32x4_RESULT(result);
+}
+
+
+RUNTIME_FUNCTION(Runtime_Float64x2Clamp) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 3);
+
+ CONVERT_ARG_CHECKED(Float64x2, self, 0);
+ CONVERT_ARG_CHECKED(Float64x2, lo, 1);
+ CONVERT_ARG_CHECKED(Float64x2, hi, 2);
+
+ float64x2_value_t result;
+ double _x = self->x() > lo->x() ? self->x() : lo->x();
+ double _y = self->y() > lo->y() ? self->y() : lo->y();
+ result.storage[0] = _x > hi->x() ? hi->x() : _x;
+ result.storage[1] = _y > hi->y() ? hi->y() : _y;
+
+ RETURN_Float64x2_RESULT(result);
+}
+
+
+RUNTIME_FUNCTION(Runtime_Float32x4ShuffleMix) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 3);
+
+ CONVERT_ARG_CHECKED(Float32x4, first, 0);
+ CONVERT_ARG_CHECKED(Float32x4, second, 1);
+ RUNTIME_ASSERT(args[2]->IsNumber());
+
+ uint32_t m = NumberToUint32(args[2]);
+ float32x4_value_t result;
+ float data1[4] = { first->x(), first->y(), first->z(), first->w() };
+ float data2[4] = { second->x(), second->y(), second->z(), second->w() };
+ result.storage[0] = data1[m & 0x3];
+ result.storage[1] = data1[(m >> 2) & 0x3];
+ result.storage[2] = data2[(m >> 4) & 0x3];
+ result.storage[3] = data2[(m >> 6) & 0x3];
+
+ RETURN_Float32x4_RESULT(result);
+}
+
+
+RUNTIME_FUNCTION(Runtime_Float32x4Select) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 3);
+
+ CONVERT_ARG_CHECKED(Int32x4, self, 0);
+ CONVERT_ARG_CHECKED(Float32x4, tv, 1);
+ CONVERT_ARG_CHECKED(Float32x4, fv, 2);
+
+ uint32_t _maskX = self->x();
+ uint32_t _maskY = self->y();
+ uint32_t _maskZ = self->z();
+ uint32_t _maskW = self->w();
+ // Extract floats and interpret them as masks.
+ float32_uint32 tvx(tv->x());
+ float32_uint32 tvy(tv->y());
+ float32_uint32 tvz(tv->z());
+ float32_uint32 tvw(tv->w());
+ float32_uint32 fvx(fv->x());
+ float32_uint32 fvy(fv->y());
+ float32_uint32 fvz(fv->z());
+ float32_uint32 fvw(fv->w());
+ // Perform select.
+ float32_uint32 tempX((_maskX & tvx.u) | (~_maskX & fvx.u));
+ float32_uint32 tempY((_maskY & tvy.u) | (~_maskY & fvy.u));
+ float32_uint32 tempZ((_maskZ & tvz.u) | (~_maskZ & fvz.u));
+ float32_uint32 tempW((_maskW & tvw.u) | (~_maskW & fvw.u));
+
+ float32x4_value_t result;
+ result.storage[0] = tempX.f;
+ result.storage[1] = tempY.f;
+ result.storage[2] = tempZ.f;
+ result.storage[3] = tempW.f;
+
+ RETURN_Float32x4_RESULT(result);
+}
+
+
+RUNTIME_FUNCTION(Runtime_Int32x4Select) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 3);
+
+ CONVERT_ARG_CHECKED(Int32x4, self, 0);
+ CONVERT_ARG_CHECKED(Int32x4, tv, 1);
+ CONVERT_ARG_CHECKED(Int32x4, fv, 2);
+
+ uint32_t _maskX = self->x();
+ uint32_t _maskY = self->y();
+ uint32_t _maskZ = self->z();
+ uint32_t _maskW = self->w();
+
+ int32x4_value_t result;
+ result.storage[0] = (_maskX & tv->x()) | (~_maskX & fv->x());
+ result.storage[1] = (_maskY & tv->y()) | (~_maskY & fv->y());
+ result.storage[2] = (_maskZ & tv->z()) | (~_maskZ & fv->z());
+ result.storage[3] = (_maskW & tv->w()) | (~_maskW & fv->w());
+
+ RETURN_Int32x4_RESULT(result);
+}
+
+
// ----------------------------------------------------------------------------
// Reference implementation for inlined runtime functions. Only used when the
// compiler does not support a certain intrinsic. Don't optimize these, but
}
U(IsStringWrapperSafeForDefaultValueOf)
-U(GeneratorNext)
-U(GeneratorThrow)
U(DebugBreakInOptimizedCode)
#undef U
CONVERT_SMI_ARG_CHECKED(index, 1);
if (!obj->IsJSDate()) {
HandleScope scope(isolate);
- return isolate->Throw(*isolate->factory()->NewTypeError(
- "not_date_object", HandleVector<Object>(NULL, 0)));
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate,
+ NewTypeError("not_date_object", HandleVector<Object>(NULL, 0)));
}
JSDate* date = JSDate::cast(obj);
if (index == 0) return date->value();
RUNTIME_FUNCTION(RuntimeReference_OneByteSeqStringSetChar) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 3);
- CONVERT_ARG_CHECKED(SeqOneByteString, string, 0);
- CONVERT_SMI_ARG_CHECKED(index, 1);
- CONVERT_SMI_ARG_CHECKED(value, 2);
+ CONVERT_INT32_ARG_CHECKED(index, 0);
+ CONVERT_INT32_ARG_CHECKED(value, 1);
+ CONVERT_ARG_CHECKED(SeqOneByteString, string, 2);
string->SeqOneByteStringSet(index, value);
return string;
}
RUNTIME_FUNCTION(RuntimeReference_TwoByteSeqStringSetChar) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 3);
- CONVERT_ARG_CHECKED(SeqTwoByteString, string, 0);
- CONVERT_SMI_ARG_CHECKED(index, 1);
- CONVERT_SMI_ARG_CHECKED(value, 2);
+ CONVERT_INT32_ARG_CHECKED(index, 0);
+ CONVERT_INT32_ARG_CHECKED(value, 1);
+ CONVERT_ARG_CHECKED(SeqTwoByteString, string, 2);
string->SeqTwoByteStringSet(index, value);
return string;
}
}
-RUNTIME_FUNCTION(RuntimeReference_FastAsciiArrayJoin) {
+RUNTIME_FUNCTION(RuntimeReference_FastOneByteArrayJoin) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 2);
return isolate->heap()->undefined_value();
}
+RUNTIME_FUNCTION(RuntimeReference_GeneratorNext) {
+ UNREACHABLE(); // Optimization disabled in SetUpGenerators().
+ return NULL;
+}
+
+
+RUNTIME_FUNCTION(RuntimeReference_GeneratorThrow) {
+ UNREACHABLE(); // Optimization disabled in SetUpGenerators().
+ return NULL;
+}
+
+
RUNTIME_FUNCTION(RuntimeReference_ClassOf) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
const Runtime::Function* Runtime::FunctionForEntry(Address entry) {
- for (size_t i = 0; i < ARRAY_SIZE(kIntrinsicFunctions); ++i) {
+ for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
if (entry == kIntrinsicFunctions[i].entry) {
return &(kIntrinsicFunctions[i]);
}