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

Side by Side Diff: src/runtime.cc

Issue 12326015: Handlify escape and unescape. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/uri.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/uri.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698