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

Unified Diff: src/runtime.cc

Issue 5862002: Version 3.0.2. (Closed)
Patch Set: Created 10 years 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
« ChangeLog ('K') | « src/regexp.js ('k') | src/runtime-profiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index bd4b89077c30066ce062b982050a8bdd65789c50..efdb50879441560074dcc4cba8421387b8271386 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -4546,53 +4546,42 @@ static MaybeObject* Runtime_URIUnescape(Arguments args) {
static const unsigned int kQuoteTableLength = 128u;
-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 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 byte JsonQuoteLengths[kQuoteTableLength] = {
6, 6, 6, 6, 6, 6, 6, 6,
2, 2, 2, 6, 2, 2, 6, 6,
@@ -4613,6 +4602,18 @@ static const byte JsonQuoteLengths[kQuoteTableLength] = {
};
+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);
@@ -4630,111 +4631,58 @@ MaybeObject* AllocateRawString<SeqAsciiString>(int length) {
template <typename Char, typename StringType>
-static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) {
+static MaybeObject* QuoteJsonString(Vector<const Char> characters) {
int length = characters.length();
- 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[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;
+ 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];
} 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++;
- }
+ quoted_length += JsonQuoteLengths[c];
}
}
- *(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);
- }
- MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length);
+ // Add space for quotes.
+ quoted_length += 2;
+
+ MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_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();
- 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];
+ 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);
}
}
- write_cursor += len;
}
}
*(write_cursor++) = '"';
-
- 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);
+ ASSERT_EQ(SeqAsciiString::kHeaderSize + quoted_length * sizeof(Char),
+ reinterpret_cast<Address>(write_cursor) - new_string->address());
return new_string;
}
@@ -6029,6 +5977,37 @@ static MaybeObject* Runtime_Math_log(Arguments args) {
}
+// 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(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -6040,11 +6019,31 @@ static MaybeObject* Runtime_Math_pow(Arguments args) {
// custom powi() function than the generic pow().
if (args[1]->IsSmi()) {
int y = Smi::cast(args[1])->value();
- return Heap::NumberFromDouble(power_double_int(x, y));
+ return Heap::NumberFromDouble(powi(x, y));
}
CONVERT_DOUBLE_CHECKED(y, args[1]);
- return Heap::AllocateHeapNumber(power_double_double(x, y));
+
+ 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 Heap::AllocateHeapNumber(sqrt(x));
+ } else if (y == -0.5) {
+ // Optimized using Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5).
+ return Heap::AllocateHeapNumber(1.0 / sqrt(x));
+ }
+ }
+
+ if (y == 0) {
+ return Smi::FromInt(1);
+ } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
+ return Heap::nan_value();
+ } else {
+ return Heap::AllocateHeapNumber(pow(x, y));
+ }
}
// Fast version of Math.pow if we know that y is not an integer and
@@ -6055,11 +6054,11 @@ static MaybeObject* Runtime_Math_pow_cfunction(Arguments args) {
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 Heap::nan_value();
+ return Heap::nan_value();
} else {
- return Heap::AllocateHeapNumber(pow(x, y));
+ return Heap::AllocateHeapNumber(pow(x, y));
}
}
@@ -7672,13 +7671,13 @@ static MaybeObject* Runtime_AllocateInNewSpace(Arguments args) {
}
-// Push an object unto an array of objects if it is not already in the
+// Push an array unto an array of arrays 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(Arguments args) {
ASSERT(args.length() == 2);
CONVERT_CHECKED(JSArray, array, args[0]);
- CONVERT_CHECKED(JSObject, element, args[1]);
+ CONVERT_CHECKED(JSArray, element, args[1]);
RUNTIME_ASSERT(array->HasFastElements());
int length = Smi::cast(array->length())->value();
FixedArray* elements = FixedArray::cast(array->elements());
« ChangeLog ('K') | « src/regexp.js ('k') | src/runtime-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698