Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Unified Diff: src/runtime.cc

Issue 6580038: [Isolates] Merge from bleeding_edge, revisions 5934-6100. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime.h ('k') | src/runtime.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
===================================================================
--- src/runtime.cc (revision 6904)
+++ src/runtime.cc (working copy)
@@ -644,23 +644,6 @@
}
-// Sets the magic number that identifies a function as one of the special
-// math functions that can be inlined.
-static MaybeObject* Runtime_SetMathFunctionId(RUNTIME_CALLING_CONVENTION) {
- RUNTIME_GET_ISOLATE;
- NoHandleAllocation ha;
- ASSERT(args.length() == 2);
- CONVERT_CHECKED(JSFunction, function, args[0]);
- CONVERT_CHECKED(Smi, id, args[1]);
- RUNTIME_ASSERT(id->value() >= 0);
- RUNTIME_ASSERT(id->value() < SharedFunctionInfo::max_math_id_number());
-
- function->shared()->set_math_function_id(id->value());
-
- return isolate->heap()->undefined_value();
-}
-
-
static MaybeObject* Runtime_IsConstructCall(RUNTIME_CALLING_CONVENTION) {
RUNTIME_GET_ISOLATE;
NoHandleAllocation ha;
@@ -3675,7 +3658,8 @@
CONVERT_ARG_CHECKED(JSObject, obj, 0);
CONVERT_CHECKED(String, name, args[1]);
CONVERT_CHECKED(Smi, flag_setter, args[2]);
- CONVERT_CHECKED(JSFunction, fun, args[3]);
+ Object* fun = args[3];
+ RUNTIME_ASSERT(fun->IsJSFunction() || fun->IsUndefined());
CONVERT_CHECKED(Smi, flag_attr, args[4]);
int unchecked = flag_attr->value();
RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
@@ -3733,7 +3717,7 @@
}
LookupResult result;
- js_object->LocalLookupRealNamedProperty(*name, &result);
+ js_object->LookupRealNamedProperty(*name, &result);
// Take special care when attributes are different and there is already
// a property. For simplicity we normalize the property which enables us
@@ -3741,7 +3725,8 @@
// map. The current version of SetObjectProperty does not handle attributes
// correctly in the case where a property is a field and is reset with
// new attributes.
- if (result.IsProperty() && attr != result.GetAttributes()) {
+ if (result.IsProperty() &&
+ (attr != result.GetAttributes() || result.type() == CALLBACKS)) {
// New attributes - normalize to avoid writing to instance descriptor
NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
// Use IgnoreAttributes version since a readonly property may be
@@ -4752,42 +4737,53 @@
static const unsigned int kQuoteTableLength = 128u;
-static const char* const JsonQuotes[kQuoteTableLength] = {
- "\\u0000", "\\u0001", "\\u0002", "\\u0003",
- "\\u0004", "\\u0005", "\\u0006", "\\u0007",
- "\\b", "\\t", "\\n", "\\u000b",
- "\\f", "\\r", "\\u000e", "\\u000f",
- "\\u0010", "\\u0011", "\\u0012", "\\u0013",
- "\\u0014", "\\u0015", "\\u0016", "\\u0017",
- "\\u0018", "\\u0019", "\\u001a", "\\u001b",
- "\\u001c", "\\u001d", "\\u001e", "\\u001f",
- NULL, NULL, "\\\"", NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- "\\\\", NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
-};
+static const int kJsonQuotesCharactersPerEntry = 8;
+static const char* const JsonQuotes =
+ "\\u0000 \\u0001 \\u0002 \\u0003 "
+ "\\u0004 \\u0005 \\u0006 \\u0007 "
+ "\\b \\t \\n \\u000b "
+ "\\f \\r \\u000e \\u000f "
+ "\\u0010 \\u0011 \\u0012 \\u0013 "
+ "\\u0014 \\u0015 \\u0016 \\u0017 "
+ "\\u0018 \\u0019 \\u001a \\u001b "
+ "\\u001c \\u001d \\u001e \\u001f "
+ " ! \\\" # "
+ "$ % & ' "
+ "( ) * + "
+ ", - . / "
+ "0 1 2 3 "
+ "4 5 6 7 "
+ "8 9 : ; "
+ "< = > ? "
+ "@ A B C "
+ "D E F G "
+ "H I J K "
+ "L M N O "
+ "P Q R S "
+ "T U V W "
+ "X Y Z [ "
+ "\\\\ ] ^ _ "
+ "` a b c "
+ "d e f g "
+ "h i j k "
+ "l m n o "
+ "p q r s "
+ "t u v w "
+ "x y z { "
+ "| } ~ \177 ";
+// For a string that is less than 32k characters it should always be
+// possible to allocate it in new space.
+static const int kMaxGuaranteedNewSpaceString = 32 * 1024;
+
+
+// Doing JSON quoting cannot make the string more than this many times larger.
+static const int kJsonQuoteWorstCaseBlowup = 6;
+
+
+// Covers the entire ASCII range (all other characters are unchanged by JSON
+// quoting).
static const byte JsonQuoteLengths[kQuoteTableLength] = {
6, 6, 6, 6, 6, 6, 6, 6,
2, 2, 2, 6, 2, 2, 6, 6,
@@ -4808,18 +4804,6 @@
};
-template <typename Char>
-Char* WriteString(Char* dst, const char* src_string) {
- char c;
- for (c = *src_string; c; c = *src_string) {
- *dst = c;
- dst++;
- src_string++;
- }
- return dst;
-}
-
-
template <typename StringType>
MaybeObject* AllocateRawString(int length);
@@ -4837,61 +4821,111 @@
template <typename Char, typename StringType>
-static MaybeObject* QuoteJsonString(Vector<const Char> characters) {
+static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) {
int length = characters.length();
- int quoted_length = 0;
- for (int i = 0; i < length; i++) {
- unsigned int c = characters[i];
- if (sizeof(Char) > 1u) {
- quoted_length += (c >= kQuoteTableLength) ? 1 : JsonQuoteLengths[c];
+ const Char* read_cursor = characters.start();
+ const Char* end = read_cursor + length;
+ const int kSpaceForQuotes = 2;
+ int quoted_length = kSpaceForQuotes;
+ while (read_cursor < end) {
+ Char c = *(read_cursor++);
+ if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
+ quoted_length++;
} else {
- quoted_length += JsonQuoteLengths[c];
+ quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
}
}
+ MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length);
+ Object* new_object;
+ if (!new_alloc->ToObject(&new_object)) {
+ return new_alloc;
+ }
+ StringType* new_string = StringType::cast(new_object);
+
+ Char* write_cursor = reinterpret_cast<Char*>(
+ new_string->address() + SeqAsciiString::kHeaderSize);
+ *(write_cursor++) = '"';
+
+ read_cursor = characters.start();
+ while (read_cursor < end) {
+ Char c = *(read_cursor++);
+ if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
+ *(write_cursor++) = c;
+ } else {
+ int len = JsonQuoteLengths[static_cast<unsigned>(c)];
+ const char* replacement = JsonQuotes +
+ static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
+ for (int i = 0; i < len; i++) {
+ *write_cursor++ = *replacement++;
+ }
+ }
+ }
+ *(write_cursor++) = '"';
+ return new_string;
+}
+
+
+template <typename Char, typename StringType>
+static MaybeObject* QuoteJsonString(Vector<const Char> characters) {
+ int length = characters.length();
COUNTERS->quote_json_char_count()->Increment(length);
+ const int kSpaceForQuotes = 2;
+ int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes;
+ if (worst_case_length > kMaxGuaranteedNewSpaceString) {
+ return SlowQuoteJsonString<Char, StringType>(characters);
+ }
- // Add space for quotes.
- quoted_length += 2;
-
- MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length);
+ MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length);
Object* new_object;
if (!new_alloc->ToObject(&new_object)) {
- COUNTERS->quote_json_char_recount()->Increment(length);
return new_alloc;
}
+ if (!HEAP->new_space()->Contains(new_object)) {
+ // Even if our string is small enough to fit in new space we still have to
+ // handle it being allocated in old space as may happen in the third
+ // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in
+ // CEntryStub::GenerateCore.
+ return SlowQuoteJsonString<Char, StringType>(characters);
+ }
StringType* new_string = StringType::cast(new_object);
+ ASSERT(HEAP->new_space()->Contains(new_string));
-
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
Char* write_cursor = reinterpret_cast<Char*>(
new_string->address() + SeqAsciiString::kHeaderSize);
*(write_cursor++) = '"';
+
const Char* read_cursor = characters.start();
- if (quoted_length == length + 2) {
- CopyChars(write_cursor, read_cursor, length);
- write_cursor += length;
- } else {
- const Char* end = read_cursor + length;
- while (read_cursor < end) {
- Char c = *(read_cursor++);
- if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
- *(write_cursor++) = c;
- } else {
- const char* replacement = JsonQuotes[static_cast<unsigned>(c)];
- if (!replacement) {
- *(write_cursor++) = c;
- } else {
- write_cursor = WriteString(write_cursor, replacement);
+ const Char* end = read_cursor + length;
+ while (read_cursor < end) {
+ Char c = *(read_cursor++);
+ if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
+ *(write_cursor++) = c;
+ } else {
+ int len = JsonQuoteLengths[static_cast<unsigned>(c)];
+ const char* replacement = JsonQuotes +
+ static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
+ write_cursor[0] = replacement[0];
+ if (len > 1) {
+ write_cursor[1] = replacement[1];
+ if (len > 2) {
+ ASSERT(len == 6);
+ write_cursor[2] = replacement[2];
+ write_cursor[3] = replacement[3];
+ write_cursor[4] = replacement[4];
+ write_cursor[5] = replacement[5];
}
}
+ write_cursor += len;
}
}
*(write_cursor++) = '"';
- ASSERT_EQ(
- static_cast<int64_t>(
- SeqAsciiString::kHeaderSize + quoted_length * sizeof(Char)),
- static_cast<int64_t>(
- reinterpret_cast<Address>(write_cursor) - new_string->address()));
+
+ int final_length = static_cast<int>(
+ write_cursor - reinterpret_cast<Char*>(
+ new_string->address() + SeqAsciiString::kHeaderSize));
+ HEAP->new_space()->ShrinkStringAtAllocationBoundary<StringType>(new_string,
+ final_length);
return new_string;
}
@@ -6256,37 +6290,6 @@
}
-// Helper function to compute x^y, where y is known to be an
-// integer. Uses binary decomposition to limit the number of
-// multiplications; see the discussion in "Hacker's Delight" by Henry
-// S. Warren, Jr., figure 11-6, page 213.
-static double powi(double x, int y) {
- ASSERT(y != kMinInt);
- unsigned n = (y < 0) ? -y : y;
- double m = x;
- double p = 1;
- while (true) {
- if ((n & 1) != 0) p *= m;
- n >>= 1;
- if (n == 0) {
- if (y < 0) {
- // Unfortunately, we have to be careful when p has reached
- // infinity in the computation, because sometimes the higher
- // internal precision in the pow() implementation would have
- // given us a finite p. This happens very rarely.
- double result = 1.0 / p;
- return (result == 0 && isinf(p))
- ? pow(x, static_cast<double>(y)) // Avoid pow(double, int).
- : result;
- } else {
- return p;
- }
- }
- m *= m;
- }
-}
-
-
static MaybeObject* Runtime_Math_pow(RUNTIME_CALLING_CONVENTION) {
RUNTIME_GET_ISOLATE;
NoHandleAllocation ha;
@@ -6299,31 +6302,11 @@
// custom powi() function than the generic pow().
if (args[1]->IsSmi()) {
int y = Smi::cast(args[1])->value();
- return isolate->heap()->NumberFromDouble(powi(x, y));
+ return isolate->heap()->NumberFromDouble(power_double_int(x, y));
}
CONVERT_DOUBLE_CHECKED(y, args[1]);
-
- if (!isinf(x)) {
- if (y == 0.5) {
- // It's not uncommon to use Math.pow(x, 0.5) to compute the
- // square root of a number. To speed up such computations, we
- // explictly check for this case and use the sqrt() function
- // which is faster than pow().
- return isolate->heap()->AllocateHeapNumber(sqrt(x));
- } else if (y == -0.5) {
- // Optimized using Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5).
- return isolate->heap()->AllocateHeapNumber(1.0 / sqrt(x));
- }
- }
-
- if (y == 0) {
- return Smi::FromInt(1);
- } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
- return isolate->heap()->nan_value();
- } else {
- return isolate->heap()->AllocateHeapNumber(pow(x, y));
- }
+ return isolate->heap()->AllocateHeapNumber(power_double_double(x, y));
}
// Fast version of Math.pow if we know that y is not an integer and
@@ -6335,11 +6318,11 @@
CONVERT_DOUBLE_CHECKED(x, args[0]);
CONVERT_DOUBLE_CHECKED(y, args[1]);
if (y == 0) {
- return Smi::FromInt(1);
+ return Smi::FromInt(1);
} else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
- return isolate->heap()->nan_value();
+ return isolate->heap()->nan_value();
} else {
- return isolate->heap()->AllocateHeapNumber(pow(x, y));
+ return isolate->heap()->AllocateHeapNumber(pow(x, y));
}
}
@@ -7194,12 +7177,17 @@
if (CompileOptimized(function, ast_id) && function->IsOptimized()) {
DeoptimizationInputData* data = DeoptimizationInputData::cast(
function->code()->deoptimization_data());
- if (FLAG_trace_osr) {
- PrintF("[on-stack replacement offset %d in optimized code]\n",
+ if (data->OsrPcOffset()->value() >= 0) {
+ if (FLAG_trace_osr) {
+ PrintF("[on-stack replacement offset %d in optimized code]\n",
data->OsrPcOffset()->value());
+ }
+ ASSERT(data->OsrAstId()->value() == ast_id);
+ } else {
+ // We may never generate the desired OSR entry if we emit an
+ // early deoptimize.
+ succeeded = false;
}
- ASSERT(data->OsrAstId()->value() == ast_id);
- ASSERT(data->OsrPcOffset()->value() >= 0);
} else {
succeeded = false;
}
@@ -7533,7 +7521,7 @@
// extension object itself.
if ((attributes & READ_ONLY) == 0 ||
(context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
- Handle<Object> set = SetProperty(context_ext, name, value, attributes);
+ Handle<Object> set = SetProperty(context_ext, name, value, NONE);
if (set.is_null()) {
// Failure::Exception is converted to a null handle in the
// handle-based methods such as SetProperty. We therefore need
@@ -8021,14 +8009,14 @@
}
-// Push an array unto an array of arrays if it is not already in the
+// Push an object unto an array of objects if it is not already in the
// array. Returns true if the element was pushed on the stack and
// false otherwise.
static MaybeObject* Runtime_PushIfAbsent(RUNTIME_CALLING_CONVENTION) {
RUNTIME_GET_ISOLATE;
ASSERT(args.length() == 2);
CONVERT_CHECKED(JSArray, array, args[0]);
- CONVERT_CHECKED(JSArray, element, args[1]);
+ CONVERT_CHECKED(JSObject, element, args[1]);
RUNTIME_ASSERT(array->HasFastElements());
int length = Smi::cast(array->length())->value();
FixedArray* elements = FixedArray::cast(array->elements());
@@ -10124,7 +10112,7 @@
// Check the execution state and decode arguments frame and source to be
// evaluated.
- ASSERT(args.length() == 4);
+ ASSERT(args.length() == 5);
Object* check_result;
{ MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args,
isolate);
@@ -10135,6 +10123,7 @@
CONVERT_CHECKED(Smi, wrapped_id, args[1]);
CONVERT_ARG_CHECKED(String, source, 2);
CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
+ Handle<Object> additional_context(args[4]);
// Handle the processing of break.
DisableBreak disable_break_save(disable_break);
@@ -10187,6 +10176,11 @@
Handle<Context> function_context(frame_context->fcontext());
context = CopyWithContextChain(frame_context, context);
+ if (additional_context->IsJSObject()) {
+ context = isolate->factory()->NewWithContext(context,
+ Handle<JSObject>::cast(additional_context), false);
+ }
+
// Wrap the evaluation statement in a new function compiled in the newly
// created context. The function has one parameter which has to be called
// 'arguments'. This it to have access to what would have been 'arguments' in
@@ -10241,7 +10235,7 @@
// Check the execution state and decode arguments frame and source to be
// evaluated.
- ASSERT(args.length() == 3);
+ ASSERT(args.length() == 4);
Object* check_result;
{ MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args,
isolate);
@@ -10251,6 +10245,7 @@
}
CONVERT_ARG_CHECKED(String, source, 1);
CONVERT_BOOLEAN_CHECKED(disable_break, args[2]);
+ Handle<Object> additional_context(args[3]);
// Handle the processing of break.
DisableBreak disable_break_save(disable_break);
@@ -10269,11 +10264,26 @@
// debugger was invoked.
Handle<Context> context = isolate->global_context();
+ bool is_global = true;
+
+ if (additional_context->IsJSObject()) {
+ // Create a function context first, than put 'with' context on top of it.
+ Handle<JSFunction> go_between = isolate->factory()->NewFunction(
+ isolate->factory()->empty_string(),
+ isolate->factory()->undefined_value());
+ go_between->set_context(*context);
+ context =
+ isolate->factory()->NewFunctionContext(
+ Context::MIN_CONTEXT_SLOTS, go_between);
+ context->set_extension(JSObject::cast(*additional_context));
+ is_global = false;
+ }
+
// Compile the source to be evaluated.
Handle<SharedFunctionInfo> shared =
Compiler::CompileEval(source,
context,
- true);
+ is_global);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Handle<JSFunction>(
« no previous file with comments | « src/runtime.h ('k') | src/runtime.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698