| 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 |