OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 #include "liveedit.h" | 51 #include "liveedit.h" |
52 #include "misc-intrinsics.h" | 52 #include "misc-intrinsics.h" |
53 #include "parser.h" | 53 #include "parser.h" |
54 #include "platform.h" | 54 #include "platform.h" |
55 #include "runtime-profiler.h" | 55 #include "runtime-profiler.h" |
56 #include "runtime.h" | 56 #include "runtime.h" |
57 #include "scopeinfo.h" | 57 #include "scopeinfo.h" |
58 #include "smart-pointers.h" | 58 #include "smart-pointers.h" |
59 #include "string-search.h" | 59 #include "string-search.h" |
60 #include "stub-cache.h" | 60 #include "stub-cache.h" |
| 61 #include "uri.h" |
61 #include "v8threads.h" | 62 #include "v8threads.h" |
62 #include "vm-state-inl.h" | 63 #include "vm-state-inl.h" |
63 | 64 |
64 namespace v8 { | 65 namespace v8 { |
65 namespace internal { | 66 namespace internal { |
66 | 67 |
67 | 68 |
68 #define RUNTIME_ASSERT(value) \ | 69 #define RUNTIME_ASSERT(value) \ |
69 if (!(value)) return isolate->ThrowIllegalOperation(); | 70 if (!(value)) return isolate->ThrowIllegalOperation(); |
70 | 71 |
(...skipping 5048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5119 } | 5120 } |
5120 | 5121 |
5121 | 5122 |
5122 RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) { | 5123 RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) { |
5123 CONVERT_ARG_CHECKED(SeqString, string, 0); | 5124 CONVERT_ARG_CHECKED(SeqString, string, 0); |
5124 CONVERT_SMI_ARG_CHECKED(new_length, 1); | 5125 CONVERT_SMI_ARG_CHECKED(new_length, 1); |
5125 return string->Truncate(new_length); | 5126 return string->Truncate(new_length); |
5126 } | 5127 } |
5127 | 5128 |
5128 | 5129 |
5129 // kNotEscaped is generated by the following: | |
5130 // | |
5131 // #!/bin/perl | |
5132 // for (my $i = 0; $i < 256; $i++) { | |
5133 // print "\n" if $i % 16 == 0; | |
5134 // my $c = chr($i); | |
5135 // my $escaped = 1; | |
5136 // $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#; | |
5137 // print $escaped ? "0, " : "1, "; | |
5138 // } | |
5139 | |
5140 | |
5141 static bool IsNotEscaped(uint16_t character) { | |
5142 // Only for 8 bit characters, the rest are always escaped (in a different way) | |
5143 ASSERT(character < 256); | |
5144 static const char kNotEscaped[256] = { | |
5145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5147 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, | |
5148 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, | |
5149 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
5150 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, | |
5151 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
5152 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, | |
5153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
5161 }; | |
5162 return kNotEscaped[character] != 0; | |
5163 } | |
5164 | |
5165 | |
5166 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) { | 5130 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) { |
5167 const char hex_chars[] = "0123456789ABCDEF"; | |
5168 NoHandleAllocation ha; | |
5169 ASSERT(args.length() == 1); | 5131 ASSERT(args.length() == 1); |
5170 CONVERT_ARG_CHECKED(String, source, 0); | 5132 HandleScope scope(isolate); |
5171 | 5133 CONVERT_ARG_HANDLE_CHECKED(String, source, 0); |
5172 source->TryFlatten(); | 5134 Handle<String> string = FlattenGetString(source); |
5173 | 5135 String::FlatContent content = string->GetFlatContent(); |
5174 int escaped_length = 0; | 5136 ASSERT(content.IsFlat()); |
5175 int length = source->length(); | 5137 Handle<String> result = |
5176 { | 5138 content.IsAscii() ? URIEscape::Escape<uint8_t>(isolate, source) |
5177 Access<ConsStringIteratorOp> op( | 5139 : URIEscape::Escape<uc16>(isolate, source); |
5178 isolate->runtime_state()->string_iterator()); | 5140 if (result.is_null()) return Failure::OutOfMemoryException(0x12); |
5179 StringCharacterStream stream(source, op.value()); | 5141 return *result; |
5180 while (stream.HasMore()) { | |
5181 uint16_t character = stream.GetNext(); | |
5182 if (character >= 256) { | |
5183 escaped_length += 6; | |
5184 } else if (IsNotEscaped(character)) { | |
5185 escaped_length++; | |
5186 } else { | |
5187 escaped_length += 3; | |
5188 } | |
5189 // We don't allow strings that are longer than a maximal length. | |
5190 ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow. | |
5191 if (escaped_length > String::kMaxLength) { | |
5192 isolate->context()->mark_out_of_memory(); | |
5193 return Failure::OutOfMemoryException(0x12); | |
5194 } | |
5195 } | |
5196 } | |
5197 // No length change implies no change. Return original string if no change. | |
5198 if (escaped_length == length) { | |
5199 return source; | |
5200 } | |
5201 Object* o; | |
5202 { MaybeObject* maybe_o = | |
5203 isolate->heap()->AllocateRawOneByteString(escaped_length); | |
5204 if (!maybe_o->ToObject(&o)) return maybe_o; | |
5205 } | |
5206 String* destination = String::cast(o); | |
5207 int dest_position = 0; | |
5208 | |
5209 Access<ConsStringIteratorOp> op( | |
5210 isolate->runtime_state()->string_iterator()); | |
5211 StringCharacterStream stream(source, op.value()); | |
5212 while (stream.HasMore()) { | |
5213 uint16_t chr = stream.GetNext(); | |
5214 if (chr >= 256) { | |
5215 destination->Set(dest_position, '%'); | |
5216 destination->Set(dest_position+1, 'u'); | |
5217 destination->Set(dest_position+2, hex_chars[chr >> 12]); | |
5218 destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]); | |
5219 destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]); | |
5220 destination->Set(dest_position+5, hex_chars[chr & 0xf]); | |
5221 dest_position += 6; | |
5222 } else if (IsNotEscaped(chr)) { | |
5223 destination->Set(dest_position, chr); | |
5224 dest_position++; | |
5225 } else { | |
5226 destination->Set(dest_position, '%'); | |
5227 destination->Set(dest_position+1, hex_chars[chr >> 4]); | |
5228 destination->Set(dest_position+2, hex_chars[chr & 0xf]); | |
5229 dest_position += 3; | |
5230 } | |
5231 } | |
5232 return destination; | |
5233 } | |
5234 | |
5235 | |
5236 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) { | |
5237 static const signed char kHexValue['g'] = { | |
5238 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
5239 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
5240 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
5241 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, | |
5242 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
5243 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
5244 -1, 10, 11, 12, 13, 14, 15 }; | |
5245 | |
5246 if (character1 > 'f') return -1; | |
5247 int hi = kHexValue[character1]; | |
5248 if (hi == -1) return -1; | |
5249 if (character2 > 'f') return -1; | |
5250 int lo = kHexValue[character2]; | |
5251 if (lo == -1) return -1; | |
5252 return (hi << 4) + lo; | |
5253 } | |
5254 | |
5255 | |
5256 static inline int Unescape(String* source, | |
5257 int i, | |
5258 int length, | |
5259 int* step) { | |
5260 uint16_t character = source->Get(i); | |
5261 int32_t hi = 0; | |
5262 int32_t lo = 0; | |
5263 if (character == '%' && | |
5264 i <= length - 6 && | |
5265 source->Get(i + 1) == 'u' && | |
5266 (hi = TwoDigitHex(source->Get(i + 2), | |
5267 source->Get(i + 3))) != -1 && | |
5268 (lo = TwoDigitHex(source->Get(i + 4), | |
5269 source->Get(i + 5))) != -1) { | |
5270 *step = 6; | |
5271 return (hi << 8) + lo; | |
5272 } else if (character == '%' && | |
5273 i <= length - 3 && | |
5274 (lo = TwoDigitHex(source->Get(i + 1), | |
5275 source->Get(i + 2))) != -1) { | |
5276 *step = 3; | |
5277 return lo; | |
5278 } else { | |
5279 *step = 1; | |
5280 return character; | |
5281 } | |
5282 } | 5142 } |
5283 | 5143 |
5284 | 5144 |
5285 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) { | 5145 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) { |
5286 NoHandleAllocation ha; | |
5287 ASSERT(args.length() == 1); | 5146 ASSERT(args.length() == 1); |
5288 CONVERT_ARG_CHECKED(String, source, 0); | 5147 HandleScope scope(isolate); |
5289 | 5148 CONVERT_ARG_HANDLE_CHECKED(String, source, 0); |
5290 source->TryFlatten(); | 5149 Handle<String> string = FlattenGetString(source); |
5291 | 5150 String::FlatContent content = string->GetFlatContent(); |
5292 bool one_byte = true; | 5151 ASSERT(content.IsFlat()); |
5293 int length = source->length(); | 5152 return content.IsAscii() ? *URIUnescape::Unescape<uint8_t>(isolate, source) |
5294 | 5153 : *URIUnescape::Unescape<uc16>(isolate, source); |
5295 int unescaped_length = 0; | |
5296 for (int i = 0; i < length; unescaped_length++) { | |
5297 int step; | |
5298 if (Unescape(source, i, length, &step) > String::kMaxOneByteCharCode) { | |
5299 one_byte = false; | |
5300 } | |
5301 i += step; | |
5302 } | |
5303 | |
5304 // No length change implies no change. Return original string if no change. | |
5305 if (unescaped_length == length) | |
5306 return source; | |
5307 | |
5308 Object* o; | |
5309 { MaybeObject* maybe_o = | |
5310 one_byte ? | |
5311 isolate->heap()->AllocateRawOneByteString(unescaped_length) : | |
5312 isolate->heap()->AllocateRawTwoByteString(unescaped_length); | |
5313 if (!maybe_o->ToObject(&o)) return maybe_o; | |
5314 } | |
5315 String* destination = String::cast(o); | |
5316 | |
5317 int dest_position = 0; | |
5318 for (int i = 0; i < length; dest_position++) { | |
5319 int step; | |
5320 destination->Set(dest_position, Unescape(source, i, length, &step)); | |
5321 i += step; | |
5322 } | |
5323 return destination; | |
5324 } | 5154 } |
5325 | 5155 |
5326 | 5156 |
5327 static const unsigned int kQuoteTableLength = 128u; | 5157 static const unsigned int kQuoteTableLength = 128u; |
5328 | 5158 |
5329 static const int kJsonQuotesCharactersPerEntry = 8; | 5159 static const int kJsonQuotesCharactersPerEntry = 8; |
5330 static const char* const JsonQuotes = | 5160 static const char* const JsonQuotes = |
5331 "\\u0000 \\u0001 \\u0002 \\u0003 " | 5161 "\\u0000 \\u0001 \\u0002 \\u0003 " |
5332 "\\u0004 \\u0005 \\u0006 \\u0007 " | 5162 "\\u0004 \\u0005 \\u0006 \\u0007 " |
5333 "\\b \\t \\n \\u000b " | 5163 "\\b \\t \\n \\u000b " |
(...skipping 8175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13509 // Handle last resort GC and make sure to allow future allocations | 13339 // Handle last resort GC and make sure to allow future allocations |
13510 // to grow the heap without causing GCs (if possible). | 13340 // to grow the heap without causing GCs (if possible). |
13511 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13341 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13512 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13342 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
13513 "Runtime::PerformGC"); | 13343 "Runtime::PerformGC"); |
13514 } | 13344 } |
13515 } | 13345 } |
13516 | 13346 |
13517 | 13347 |
13518 } } // namespace v8::internal | 13348 } } // namespace v8::internal |
OLD | NEW |