summaryrefslogtreecommitdiffstats
path: root/src/runtime.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime.cc')
-rw-r--r--src/runtime.cc163
1 files changed, 140 insertions, 23 deletions
diff --git a/src/runtime.cc b/src/runtime.cc
index 4e1940d8..8fd62c98 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -34,18 +34,17 @@
#include "arguments.h"
#include "compiler.h"
#include "cpu.h"
-#include "dateparser.h"
#include "dateparser-inl.h"
#include "debug.h"
#include "execution.h"
#include "jsregexp.h"
+#include "parser.h"
#include "platform.h"
#include "runtime.h"
#include "scopeinfo.h"
-#include "v8threads.h"
#include "smart-pointer.h"
-#include "parser.h"
#include "stub-cache.h"
+#include "v8threads.h"
namespace v8 {
namespace internal {
@@ -157,7 +156,7 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
// Deep copy local elements.
// Pixel elements cannot be created using an object literal.
- ASSERT(!copy->HasPixelElements());
+ ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements());
switch (copy->GetElementsKind()) {
case JSObject::FAST_ELEMENTS: {
FixedArray* elements = FixedArray::cast(copy->elements());
@@ -522,7 +521,7 @@ static Object* Runtime_GetTemplateField(Arguments args) {
RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
type == OBJECT_TEMPLATE_INFO_TYPE);
RUNTIME_ASSERT(offset > 0);
- if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
+ if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
} else {
RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
@@ -578,8 +577,8 @@ static Object* Runtime_DeclareGlobals(Arguments args) {
HandleScope scope;
Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
- CONVERT_ARG_CHECKED(FixedArray, pairs, 0);
- Handle<Context> context = args.at<Context>(1);
+ Handle<Context> context = args.at<Context>(0);
+ CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
bool is_eval = Smi::cast(args[2])->value() == 1;
// Compute the property attributes. According to ECMA-262, section
@@ -3252,8 +3251,8 @@ static Object* Runtime_URIEscape(Arguments args) {
} else {
escaped_length += 3;
}
- // We don't allow strings that are longer than Smi range.
- if (!Smi::IsValid(escaped_length)) {
+ // We don't allow strings that are longer than a maximal length.
+ if (escaped_length > String::kMaxLength) {
Top::context()->mark_out_of_memory();
return Failure::OutOfMemoryException();
}
@@ -3584,6 +3583,36 @@ static Object* Runtime_StringToUpperCase(Arguments args) {
return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping);
}
+static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
+ return unibrow::WhiteSpace::Is(c) || c == 0x200b;
+}
+
+static Object* Runtime_StringTrim(Arguments args) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 3);
+
+ CONVERT_CHECKED(String, s, args[0]);
+ CONVERT_BOOLEAN_CHECKED(trimLeft, args[1]);
+ CONVERT_BOOLEAN_CHECKED(trimRight, args[2]);
+
+ s->TryFlattenIfNotFlat();
+ int length = s->length();
+
+ int left = 0;
+ if (trimLeft) {
+ while (left < length && IsTrimWhiteSpace(s->Get(left))) {
+ left++;
+ }
+ }
+
+ int right = length;
+ if (trimRight) {
+ while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
+ right--;
+ }
+ }
+ return s->Slice(left, right);
+}
bool Runtime::IsUpperCaseChar(uint16_t ch) {
unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
@@ -3713,14 +3742,7 @@ static Object* Runtime_NumberMod(Arguments args) {
CONVERT_DOUBLE_CHECKED(x, args[0]);
CONVERT_DOUBLE_CHECKED(y, args[1]);
-#if defined WIN32 || defined _WIN64
- // Workaround MS fmod bugs. ECMA-262 says:
- // dividend is finite and divisor is an infinity => result equals dividend
- // dividend is a zero and divisor is nonzero finite => result equals dividend
- if (!(isfinite(x) && (!isfinite(y) && !isnan(y))) &&
- !(x == 0 && (y != 0 && isfinite(y))))
-#endif
- x = fmod(x, y);
+ x = modulo(x, y);
// NewNumberFromDouble may return a Smi instead of a Number object
return Heap::NewNumberFromDouble(x);
}
@@ -3804,10 +3826,6 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
} else if (elt->IsString()) {
String* element = String::cast(elt);
int element_length = element->length();
- if (!Smi::IsValid(element_length + position)) {
- Top::context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
- }
position += element_length;
if (ascii && !element->IsAsciiRepresentation()) {
ascii = false;
@@ -3815,6 +3833,10 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
} else {
return Top::Throw(Heap::illegal_argument_symbol());
}
+ if (position > String::kMaxLength) {
+ Top::context()->mark_out_of_memory();
+ return Failure::OutOfMemoryException();
+ }
}
int length = position;
@@ -4338,8 +4360,8 @@ static Object* Runtime_NewArgumentsFast(Arguments args) {
static Object* Runtime_NewClosure(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(JSFunction, boilerplate, 0);
- CONVERT_ARG_CHECKED(Context, context, 1);
+ CONVERT_ARG_CHECKED(Context, context, 0);
+ CONVERT_ARG_CHECKED(JSFunction, boilerplate, 1);
Handle<JSFunction> result =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -5244,6 +5266,47 @@ class ArrayConcatVisitor {
};
+template<class ExternalArrayClass, class ElementType>
+static uint32_t IterateExternalArrayElements(Handle<JSObject> receiver,
+ bool elements_are_ints,
+ bool elements_are_guaranteed_smis,
+ uint32_t range,
+ ArrayConcatVisitor* visitor) {
+ Handle<ExternalArrayClass> array(
+ ExternalArrayClass::cast(receiver->elements()));
+ uint32_t len = Min(static_cast<uint32_t>(array->length()), range);
+
+ if (visitor != NULL) {
+ if (elements_are_ints) {
+ if (elements_are_guaranteed_smis) {
+ for (uint32_t j = 0; j < len; j++) {
+ Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j))));
+ visitor->visit(j, e);
+ }
+ } else {
+ for (uint32_t j = 0; j < len; j++) {
+ int64_t val = static_cast<int64_t>(array->get(j));
+ if (Smi::IsValid(static_cast<intptr_t>(val))) {
+ Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
+ visitor->visit(j, e);
+ } else {
+ Handle<Object> e(
+ Heap::AllocateHeapNumber(static_cast<ElementType>(val)));
+ visitor->visit(j, e);
+ }
+ }
+ }
+ } else {
+ for (uint32_t j = 0; j < len; j++) {
+ Handle<Object> e(Heap::AllocateHeapNumber(array->get(j)));
+ visitor->visit(j, e);
+ }
+ }
+ }
+
+ return len;
+}
+
/**
* A helper function that visits elements of a JSObject. Only elements
* whose index between 0 and range (exclusive) are visited.
@@ -5293,6 +5356,48 @@ static uint32_t IterateElements(Handle<JSObject> receiver,
}
break;
}
+ case JSObject::EXTERNAL_BYTE_ELEMENTS: {
+ num_of_elements =
+ IterateExternalArrayElements<ExternalByteArray, int8_t>(
+ receiver, true, true, range, visitor);
+ break;
+ }
+ case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
+ num_of_elements =
+ IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
+ receiver, true, true, range, visitor);
+ break;
+ }
+ case JSObject::EXTERNAL_SHORT_ELEMENTS: {
+ num_of_elements =
+ IterateExternalArrayElements<ExternalShortArray, int16_t>(
+ receiver, true, true, range, visitor);
+ break;
+ }
+ case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
+ num_of_elements =
+ IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
+ receiver, true, true, range, visitor);
+ break;
+ }
+ case JSObject::EXTERNAL_INT_ELEMENTS: {
+ num_of_elements =
+ IterateExternalArrayElements<ExternalIntArray, int32_t>(
+ receiver, true, false, range, visitor);
+ break;
+ }
+ case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
+ num_of_elements =
+ IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
+ receiver, true, false, range, visitor);
+ break;
+ }
+ case JSObject::EXTERNAL_FLOAT_ELEMENTS: {
+ num_of_elements =
+ IterateExternalArrayElements<ExternalFloatArray, float>(
+ receiver, false, false, range, visitor);
+ break;
+ }
case JSObject::DICTIONARY_ELEMENTS: {
Handle<NumberDictionary> dict(receiver->element_dictionary());
uint32_t capacity = dict->Capacity();
@@ -7630,6 +7735,18 @@ static Object* Runtime_CollectStackTrace(Arguments args) {
}
+// Returns V8 version as a string.
+static Object* Runtime_GetV8Version(Arguments args) {
+ ASSERT_EQ(args.length(), 0);
+
+ NoHandleAllocation ha;
+
+ const char* version_string = v8::V8::GetVersion();
+
+ return Heap::AllocateStringFromAscii(CStrVector(version_string), NOT_TENURED);
+}
+
+
static Object* Runtime_Abort(Arguments args) {
ASSERT(args.length() == 2);
OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +