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

Side by Side Diff: src/runtime.cc

Issue 1148007: Merge bleeding_edge from version 2.1.3 up to revision 4205... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 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
« src/objects.h ('K') | « src/runtime.h ('k') | src/scopes.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <stdlib.h> 28 #include <stdlib.h>
29 29
30 #include "v8.h" 30 #include "v8.h"
31 31
32 #include "accessors.h" 32 #include "accessors.h"
33 #include "api.h" 33 #include "api.h"
34 #include "arguments.h" 34 #include "arguments.h"
35 #include "codegen.h"
35 #include "compiler.h" 36 #include "compiler.h"
36 #include "cpu.h" 37 #include "cpu.h"
37 #include "dateparser-inl.h" 38 #include "dateparser-inl.h"
38 #include "debug.h" 39 #include "debug.h"
39 #include "execution.h" 40 #include "execution.h"
40 #include "jsregexp.h" 41 #include "jsregexp.h"
41 #include "liveedit.h" 42 #include "liveedit.h"
42 #include "parser.h" 43 #include "parser.h"
43 #include "platform.h" 44 #include "platform.h"
44 #include "runtime.h" 45 #include "runtime.h"
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 } 241 }
241 242
242 243
243 static Handle<Object> CreateLiteralBoilerplate( 244 static Handle<Object> CreateLiteralBoilerplate(
244 Handle<FixedArray> literals, 245 Handle<FixedArray> literals,
245 Handle<FixedArray> constant_properties); 246 Handle<FixedArray> constant_properties);
246 247
247 248
248 static Handle<Object> CreateObjectLiteralBoilerplate( 249 static Handle<Object> CreateObjectLiteralBoilerplate(
249 Handle<FixedArray> literals, 250 Handle<FixedArray> literals,
250 Handle<FixedArray> constant_properties) { 251 Handle<FixedArray> constant_properties,
252 bool should_have_fast_elements) {
251 // Get the global context from the literals array. This is the 253 // Get the global context from the literals array. This is the
252 // context in which the function was created and we use the object 254 // context in which the function was created and we use the object
253 // function from this context to create the object literal. We do 255 // function from this context to create the object literal. We do
254 // not use the object function from the current global context 256 // not use the object function from the current global context
255 // because this might be the object function from another context 257 // because this might be the object function from another context
256 // which we should not have access to. 258 // which we should not have access to.
257 Handle<Context> context = 259 Handle<Context> context =
258 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals)); 260 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
259 261
260 bool is_result_from_cache; 262 bool is_result_from_cache;
261 Handle<Map> map = ComputeObjectLiteralMap(context, 263 Handle<Map> map = ComputeObjectLiteralMap(context,
262 constant_properties, 264 constant_properties,
263 &is_result_from_cache); 265 &is_result_from_cache);
264 266
265 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map); 267 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
268
269 // Normalize the elements of the boilerplate to save space if needed.
270 if (!should_have_fast_elements) NormalizeElements(boilerplate);
271
266 { // Add the constant properties to the boilerplate. 272 { // Add the constant properties to the boilerplate.
267 int length = constant_properties->length(); 273 int length = constant_properties->length();
268 OptimizedObjectForAddingMultipleProperties opt(boilerplate, 274 OptimizedObjectForAddingMultipleProperties opt(boilerplate,
269 length / 2, 275 length / 2,
270 !is_result_from_cache); 276 !is_result_from_cache);
271 for (int index = 0; index < length; index +=2) { 277 for (int index = 0; index < length; index +=2) {
272 Handle<Object> key(constant_properties->get(index+0)); 278 Handle<Object> key(constant_properties->get(index+0));
273 Handle<Object> value(constant_properties->get(index+1)); 279 Handle<Object> value(constant_properties->get(index+1));
274 if (value->IsFixedArray()) { 280 if (value->IsFixedArray()) {
275 // The value contains the constant_properties of a 281 // The value contains the constant_properties of a
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 Handle<JSArray>::cast(object)->SetContent(*content); 343 Handle<JSArray>::cast(object)->SetContent(*content);
338 return object; 344 return object;
339 } 345 }
340 346
341 347
342 static Handle<Object> CreateLiteralBoilerplate( 348 static Handle<Object> CreateLiteralBoilerplate(
343 Handle<FixedArray> literals, 349 Handle<FixedArray> literals,
344 Handle<FixedArray> array) { 350 Handle<FixedArray> array) {
345 Handle<FixedArray> elements = CompileTimeValue::GetElements(array); 351 Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
346 switch (CompileTimeValue::GetType(array)) { 352 switch (CompileTimeValue::GetType(array)) {
347 case CompileTimeValue::OBJECT_LITERAL: 353 case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
348 return CreateObjectLiteralBoilerplate(literals, elements); 354 return CreateObjectLiteralBoilerplate(literals, elements, true);
355 case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
356 return CreateObjectLiteralBoilerplate(literals, elements, false);
349 case CompileTimeValue::ARRAY_LITERAL: 357 case CompileTimeValue::ARRAY_LITERAL:
350 return CreateArrayLiteralBoilerplate(literals, elements); 358 return CreateArrayLiteralBoilerplate(literals, elements);
351 default: 359 default:
352 UNREACHABLE(); 360 UNREACHABLE();
353 return Handle<Object>::null(); 361 return Handle<Object>::null();
354 } 362 }
355 } 363 }
356 364
357 365
358 static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
359 HandleScope scope;
360 ASSERT(args.length() == 3);
361 // Copy the arguments.
362 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
363 CONVERT_SMI_CHECKED(literals_index, args[1]);
364 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
365
366 Handle<Object> result =
367 CreateObjectLiteralBoilerplate(literals, constant_properties);
368
369 if (result.is_null()) return Failure::Exception();
370
371 // Update the functions literal and return the boilerplate.
372 literals->set(literals_index, *result);
373
374 return *result;
375 }
376
377
378 static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) { 366 static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) {
379 // Takes a FixedArray of elements containing the literal elements of 367 // Takes a FixedArray of elements containing the literal elements of
380 // the array literal and produces JSArray with those elements. 368 // the array literal and produces JSArray with those elements.
381 // Additionally takes the literals array of the surrounding function 369 // Additionally takes the literals array of the surrounding function
382 // which contains the context from which to get the Array function 370 // which contains the context from which to get the Array function
383 // to use for creating the array literal. 371 // to use for creating the array literal.
384 HandleScope scope; 372 HandleScope scope;
385 ASSERT(args.length() == 3); 373 ASSERT(args.length() == 3);
386 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 374 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
387 CONVERT_SMI_CHECKED(literals_index, args[1]); 375 CONVERT_SMI_CHECKED(literals_index, args[1]);
388 CONVERT_ARG_CHECKED(FixedArray, elements, 2); 376 CONVERT_ARG_CHECKED(FixedArray, elements, 2);
389 377
390 Handle<Object> object = CreateArrayLiteralBoilerplate(literals, elements); 378 Handle<Object> object = CreateArrayLiteralBoilerplate(literals, elements);
391 if (object.is_null()) return Failure::Exception(); 379 if (object.is_null()) return Failure::Exception();
392 380
393 // Update the functions literal and return the boilerplate. 381 // Update the functions literal and return the boilerplate.
394 literals->set(literals_index, *object); 382 literals->set(literals_index, *object);
395 return *object; 383 return *object;
396 } 384 }
397 385
398 386
399 static Object* Runtime_CreateObjectLiteral(Arguments args) { 387 static Object* Runtime_CreateObjectLiteral(Arguments args) {
400 HandleScope scope; 388 HandleScope scope;
401 ASSERT(args.length() == 3); 389 ASSERT(args.length() == 4);
402 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 390 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
403 CONVERT_SMI_CHECKED(literals_index, args[1]); 391 CONVERT_SMI_CHECKED(literals_index, args[1]);
404 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); 392 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
393 CONVERT_SMI_CHECKED(fast_elements, args[3]);
394 bool should_have_fast_elements = fast_elements == 1;
405 395
406 // Check if boilerplate exists. If not, create it first. 396 // Check if boilerplate exists. If not, create it first.
407 Handle<Object> boilerplate(literals->get(literals_index)); 397 Handle<Object> boilerplate(literals->get(literals_index));
408 if (*boilerplate == Heap::undefined_value()) { 398 if (*boilerplate == Heap::undefined_value()) {
409 boilerplate = CreateObjectLiteralBoilerplate(literals, constant_properties); 399 boilerplate = CreateObjectLiteralBoilerplate(literals,
400 constant_properties,
401 should_have_fast_elements);
410 if (boilerplate.is_null()) return Failure::Exception(); 402 if (boilerplate.is_null()) return Failure::Exception();
411 // Update the functions literal and return the boilerplate. 403 // Update the functions literal and return the boilerplate.
412 literals->set(literals_index, *boilerplate); 404 literals->set(literals_index, *boilerplate);
413 } 405 }
414 return DeepCopyBoilerplate(JSObject::cast(*boilerplate)); 406 return DeepCopyBoilerplate(JSObject::cast(*boilerplate));
415 } 407 }
416 408
417 409
418 static Object* Runtime_CreateObjectLiteralShallow(Arguments args) { 410 static Object* Runtime_CreateObjectLiteralShallow(Arguments args) {
419 HandleScope scope; 411 HandleScope scope;
420 ASSERT(args.length() == 3); 412 ASSERT(args.length() == 4);
421 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 413 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
422 CONVERT_SMI_CHECKED(literals_index, args[1]); 414 CONVERT_SMI_CHECKED(literals_index, args[1]);
423 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); 415 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
416 CONVERT_SMI_CHECKED(fast_elements, args[3]);
417 bool should_have_fast_elements = fast_elements == 1;
424 418
425 // Check if boilerplate exists. If not, create it first. 419 // Check if boilerplate exists. If not, create it first.
426 Handle<Object> boilerplate(literals->get(literals_index)); 420 Handle<Object> boilerplate(literals->get(literals_index));
427 if (*boilerplate == Heap::undefined_value()) { 421 if (*boilerplate == Heap::undefined_value()) {
428 boilerplate = CreateObjectLiteralBoilerplate(literals, constant_properties); 422 boilerplate = CreateObjectLiteralBoilerplate(literals,
423 constant_properties,
424 should_have_fast_elements);
429 if (boilerplate.is_null()) return Failure::Exception(); 425 if (boilerplate.is_null()) return Failure::Exception();
430 // Update the functions literal and return the boilerplate. 426 // Update the functions literal and return the boilerplate.
431 literals->set(literals_index, *boilerplate); 427 literals->set(literals_index, *boilerplate);
432 } 428 }
433 return Heap::CopyJSObject(JSObject::cast(*boilerplate)); 429 return Heap::CopyJSObject(JSObject::cast(*boilerplate));
434 } 430 }
435 431
436 432
437 static Object* Runtime_CreateArrayLiteral(Arguments args) { 433 static Object* Runtime_CreateArrayLiteral(Arguments args) {
438 HandleScope scope; 434 HandleScope scope;
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after
1235 HandleScope scope; 1231 HandleScope scope;
1236 ASSERT(args.length() == 1); 1232 ASSERT(args.length() == 1);
1237 CONVERT_ARG_CHECKED(JSArray, prototype, 0); 1233 CONVERT_ARG_CHECKED(JSArray, prototype, 0);
1238 // This is necessary to enable fast checks for absence of elements 1234 // This is necessary to enable fast checks for absence of elements
1239 // on Array.prototype and below. 1235 // on Array.prototype and below.
1240 prototype->set_elements(Heap::empty_fixed_array()); 1236 prototype->set_elements(Heap::empty_fixed_array());
1241 return Smi::FromInt(0); 1237 return Smi::FromInt(0);
1242 } 1238 }
1243 1239
1244 1240
1241 static void SetCustomCallGenerator(Handle<JSFunction> function,
1242 CustomCallGenerator generator) {
1243 if (function->shared()->function_data()->IsUndefined()) {
1244 function->shared()->set_function_data(*FromCData(generator));
1245 }
1246 }
1247
1248
1249 static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder,
1250 const char* name,
1251 Builtins::Name builtin_name,
1252 CustomCallGenerator generator = NULL) {
Erik Corry 2010/03/23 10:12:44 This should be an external reference (note for lat
1253 Handle<String> key = Factory::LookupAsciiSymbol(name);
1254 Handle<Code> code(Builtins::builtin(builtin_name));
1255 Handle<JSFunction> optimized = Factory::NewFunction(key,
1256 JS_OBJECT_TYPE,
1257 JSObject::kHeaderSize,
1258 code,
1259 false);
1260 optimized->shared()->DontAdaptArguments();
1261 if (generator != NULL) {
1262 SetCustomCallGenerator(optimized, generator);
1263 }
1264 SetProperty(holder, key, optimized, NONE);
1265 return optimized;
1266 }
1267
1268
1269 static Object* CompileArrayPushCall(CallStubCompiler* compiler,
1270 Object* object,
1271 JSObject* holder,
1272 JSFunction* function,
1273 String* name,
1274 StubCompiler::CheckType check) {
1275 return compiler->CompileArrayPushCall(object, holder, function, name, check);
1276 }
1277
1278
1279 static Object* CompileArrayPopCall(CallStubCompiler* compiler,
1280 Object* object,
1281 JSObject* holder,
1282 JSFunction* function,
1283 String* name,
1284 StubCompiler::CheckType check) {
1285 return compiler->CompileArrayPopCall(object, holder, function, name, check);
1286 }
1287
1288
1289 static Object* Runtime_SpecialArrayFunctions(Arguments args) {
1290 HandleScope scope;
1291 ASSERT(args.length() == 1);
1292 CONVERT_ARG_CHECKED(JSObject, holder, 0);
1293
1294 InstallBuiltin(holder, "pop", Builtins::ArrayPop, CompileArrayPopCall);
1295 InstallBuiltin(holder, "push", Builtins::ArrayPush, CompileArrayPushCall);
1296 InstallBuiltin(holder, "shift", Builtins::ArrayShift);
1297 InstallBuiltin(holder, "unshift", Builtins::ArrayUnshift);
1298 InstallBuiltin(holder, "slice", Builtins::ArraySlice);
1299 InstallBuiltin(holder, "splice", Builtins::ArraySplice);
1300 InstallBuiltin(holder, "concat", Builtins::ArrayConcat);
1301
1302 return *holder;
1303 }
1304
1305
1245 static Object* Runtime_MaterializeRegExpLiteral(Arguments args) { 1306 static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
1246 HandleScope scope; 1307 HandleScope scope;
1247 ASSERT(args.length() == 4); 1308 ASSERT(args.length() == 4);
1248 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 1309 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
1249 int index = Smi::cast(args[1])->value(); 1310 int index = Smi::cast(args[1])->value();
1250 Handle<String> pattern = args.at<String>(2); 1311 Handle<String> pattern = args.at<String>(2);
1251 Handle<String> flags = args.at<String>(3); 1312 Handle<String> flags = args.at<String>(3);
1252 1313
1253 // Get the RegExp function from the context in the literals array. 1314 // Get the RegExp function from the context in the literals array.
1254 // This is the RegExp function from the context in which the 1315 // This is the RegExp function from the context in which the
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1369 if (obj->IsFailure()) return obj; 1430 if (obj->IsFailure()) return obj;
1370 return args[0]; // return TOS 1431 return args[0]; // return TOS
1371 } 1432 }
1372 1433
1373 1434
1374 static Object* Runtime_FunctionIsAPIFunction(Arguments args) { 1435 static Object* Runtime_FunctionIsAPIFunction(Arguments args) {
1375 NoHandleAllocation ha; 1436 NoHandleAllocation ha;
1376 ASSERT(args.length() == 1); 1437 ASSERT(args.length() == 1);
1377 1438
1378 CONVERT_CHECKED(JSFunction, f, args[0]); 1439 CONVERT_CHECKED(JSFunction, f, args[0]);
1379 // The function_data field of the shared function info is used exclusively by 1440 return f->shared()->IsApiFunction() ? Heap::true_value()
1380 // the API. 1441 : Heap::false_value();
1381 return !f->shared()->function_data()->IsUndefined() ? Heap::true_value()
1382 : Heap::false_value();
1383 } 1442 }
1384 1443
1385 static Object* Runtime_FunctionIsBuiltin(Arguments args) { 1444 static Object* Runtime_FunctionIsBuiltin(Arguments args) {
1386 NoHandleAllocation ha; 1445 NoHandleAllocation ha;
1387 ASSERT(args.length() == 1); 1446 ASSERT(args.length() == 1);
1388 1447
1389 CONVERT_CHECKED(JSFunction, f, args[0]); 1448 CONVERT_CHECKED(JSFunction, f, args[0]);
1390 return f->IsBuiltin() ? Heap::true_value() : Heap::false_value(); 1449 return f->IsBuiltin() ? Heap::true_value() : Heap::false_value();
1391 } 1450 }
1392 1451
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after
2081 int good_suffix_shift_[kBMMaxShift + 1]; 2140 int good_suffix_shift_[kBMMaxShift + 1];
2082 int* biased_suffixes_; 2141 int* biased_suffixes_;
2083 int* biased_good_suffix_shift_; 2142 int* biased_good_suffix_shift_;
2084 DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers); 2143 DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers);
2085 }; 2144 };
2086 2145
2087 // buffers reused by BoyerMoore 2146 // buffers reused by BoyerMoore
2088 static int bad_char_occurrence[kBMAlphabetSize]; 2147 static int bad_char_occurrence[kBMAlphabetSize];
2089 static BMGoodSuffixBuffers bmgs_buffers; 2148 static BMGoodSuffixBuffers bmgs_buffers;
2090 2149
2150 // State of the string match tables.
2151 // SIMPLE: No usable content in the buffers.
2152 // BOYER_MOORE_HORSPOOL: The bad_char_occurences table has been populated.
2153 // BOYER_MOORE: The bmgs_buffers tables have also been populated.
2154 // Whenever starting with a new needle, one should call InitializeStringSearch
2155 // to determine which search strategy to use, and in the case of a long-needle
2156 // strategy, the call also initializes the algorithm to SIMPLE.
2157 enum StringSearchAlgorithm { SIMPLE_SEARCH, BOYER_MOORE_HORSPOOL, BOYER_MOORE };
2158 static StringSearchAlgorithm algorithm;
2159
2160
2091 // Compute the bad-char table for Boyer-Moore in the static buffer. 2161 // Compute the bad-char table for Boyer-Moore in the static buffer.
2092 template <typename pchar> 2162 template <typename pchar>
2093 static void BoyerMoorePopulateBadCharTable(Vector<const pchar> pattern, 2163 static void BoyerMoorePopulateBadCharTable(Vector<const pchar> pattern) {
2094 int start) { 2164 // Only preprocess at most kBMMaxShift last characters of pattern.
2165 int start = pattern.length() < kBMMaxShift ? 0
2166 : pattern.length() - kBMMaxShift;
2095 // Run forwards to populate bad_char_table, so that *last* instance 2167 // Run forwards to populate bad_char_table, so that *last* instance
2096 // of character equivalence class is the one registered. 2168 // of character equivalence class is the one registered.
2097 // Notice: Doesn't include the last character. 2169 // Notice: Doesn't include the last character.
2098 int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1 2170 int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1
2099 : kBMAlphabetSize; 2171 : kBMAlphabetSize;
2100 if (start == 0) { // All patterns less than kBMMaxShift in length. 2172 if (start == 0) { // All patterns less than kBMMaxShift in length.
2101 memset(bad_char_occurrence, -1, table_size * sizeof(*bad_char_occurrence)); 2173 memset(bad_char_occurrence, -1, table_size * sizeof(*bad_char_occurrence));
2102 } else { 2174 } else {
2103 for (int i = 0; i < table_size; i++) { 2175 for (int i = 0; i < table_size; i++) {
2104 bad_char_occurrence[i] = start - 1; 2176 bad_char_occurrence[i] = start - 1;
2105 } 2177 }
2106 } 2178 }
2107 for (int i = start; i < pattern.length() - 1; i++) { 2179 for (int i = start; i < pattern.length() - 1; i++) {
2108 pchar c = pattern[i]; 2180 pchar c = pattern[i];
2109 int bucket = (sizeof(pchar) ==1) ? c : c % kBMAlphabetSize; 2181 int bucket = (sizeof(pchar) ==1) ? c : c % kBMAlphabetSize;
2110 bad_char_occurrence[bucket] = i; 2182 bad_char_occurrence[bucket] = i;
2111 } 2183 }
2112 } 2184 }
2113 2185
2186
2114 template <typename pchar> 2187 template <typename pchar>
2115 static void BoyerMoorePopulateGoodSuffixTable(Vector<const pchar> pattern, 2188 static void BoyerMoorePopulateGoodSuffixTable(Vector<const pchar> pattern) {
2116 int start) {
2117 int m = pattern.length(); 2189 int m = pattern.length();
2190 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
2118 int len = m - start; 2191 int len = m - start;
2119 // Compute Good Suffix tables. 2192 // Compute Good Suffix tables.
2120 bmgs_buffers.init(m); 2193 bmgs_buffers.init(m);
2121 2194
2122 bmgs_buffers.shift(m-1) = 1; 2195 bmgs_buffers.shift(m-1) = 1;
2123 bmgs_buffers.suffix(m) = m + 1; 2196 bmgs_buffers.suffix(m) = m + 1;
2124 pchar last_char = pattern[m - 1]; 2197 pchar last_char = pattern[m - 1];
2125 int suffix = m + 1; 2198 int suffix = m + 1;
2126 for (int i = m; i > start;) { 2199 for (int i = m; i > start;) {
2127 for (pchar c = pattern[i - 1]; suffix <= m && c != pattern[suffix - 1];) { 2200 for (pchar c = pattern[i - 1]; suffix <= m && c != pattern[suffix - 1];) {
(...skipping 26 matching lines...) Expand all
2154 if (bmgs_buffers.shift(i) == len) { 2227 if (bmgs_buffers.shift(i) == len) {
2155 bmgs_buffers.shift(i) = suffix - start; 2228 bmgs_buffers.shift(i) = suffix - start;
2156 } 2229 }
2157 if (i == suffix) { 2230 if (i == suffix) {
2158 suffix = bmgs_buffers.suffix(suffix); 2231 suffix = bmgs_buffers.suffix(suffix);
2159 } 2232 }
2160 } 2233 }
2161 } 2234 }
2162 } 2235 }
2163 2236
2237
2164 template <typename schar, typename pchar> 2238 template <typename schar, typename pchar>
2165 static inline int CharOccurrence(int char_code) { 2239 static inline int CharOccurrence(int char_code) {
2166 if (sizeof(schar) == 1) { 2240 if (sizeof(schar) == 1) {
2167 return bad_char_occurrence[char_code]; 2241 return bad_char_occurrence[char_code];
2168 } 2242 }
2169 if (sizeof(pchar) == 1) { 2243 if (sizeof(pchar) == 1) {
2170 if (char_code > String::kMaxAsciiCharCode) { 2244 if (char_code > String::kMaxAsciiCharCode) {
2171 return -1; 2245 return -1;
2172 } 2246 }
2173 return bad_char_occurrence[char_code]; 2247 return bad_char_occurrence[char_code];
2174 } 2248 }
2175 return bad_char_occurrence[char_code % kBMAlphabetSize]; 2249 return bad_char_occurrence[char_code % kBMAlphabetSize];
2176 } 2250 }
2177 2251
2252
2178 // Restricted simplified Boyer-Moore string matching. 2253 // Restricted simplified Boyer-Moore string matching.
2179 // Uses only the bad-shift table of Boyer-Moore and only uses it 2254 // Uses only the bad-shift table of Boyer-Moore and only uses it
2180 // for the character compared to the last character of the needle. 2255 // for the character compared to the last character of the needle.
2181 template <typename schar, typename pchar> 2256 template <typename schar, typename pchar>
2182 static int BoyerMooreHorspool(Vector<const schar> subject, 2257 static int BoyerMooreHorspool(Vector<const schar> subject,
2183 Vector<const pchar> pattern, 2258 Vector<const pchar> pattern,
2184 int start_index, 2259 int start_index,
2185 bool* complete) { 2260 bool* complete) {
2261 ASSERT(algorithm <= BOYER_MOORE_HORSPOOL);
2186 int n = subject.length(); 2262 int n = subject.length();
2187 int m = pattern.length(); 2263 int m = pattern.length();
2188 // Only preprocess at most kBMMaxShift last characters of pattern.
2189 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
2190 2264
2191 BoyerMoorePopulateBadCharTable(pattern, start); 2265 int badness = -m;
2192 2266
2193 int badness = -m; // How bad we are doing without a good-suffix table. 2267 // How bad we are doing without a good-suffix table.
2194 int idx; // No matches found prior to this index. 2268 int idx; // No matches found prior to this index.
2195 pchar last_char = pattern[m - 1]; 2269 pchar last_char = pattern[m - 1];
2196 int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(last_char); 2270 int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(last_char);
2197 // Perform search 2271 // Perform search
2198 for (idx = start_index; idx <= n - m;) { 2272 for (idx = start_index; idx <= n - m;) {
2199 int j = m - 1; 2273 int j = m - 1;
2200 int c; 2274 int c;
2201 while (last_char != (c = subject[idx + j])) { 2275 while (last_char != (c = subject[idx + j])) {
2202 int bc_occ = CharOccurrence<schar, pchar>(c); 2276 int bc_occ = CharOccurrence<schar, pchar>(c);
2203 int shift = j - bc_occ; 2277 int shift = j - bc_occ;
(...skipping 24 matching lines...) Expand all
2228 } 2302 }
2229 *complete = true; 2303 *complete = true;
2230 return -1; 2304 return -1;
2231 } 2305 }
2232 2306
2233 2307
2234 template <typename schar, typename pchar> 2308 template <typename schar, typename pchar>
2235 static int BoyerMooreIndexOf(Vector<const schar> subject, 2309 static int BoyerMooreIndexOf(Vector<const schar> subject,
2236 Vector<const pchar> pattern, 2310 Vector<const pchar> pattern,
2237 int idx) { 2311 int idx) {
2312 ASSERT(algorithm <= BOYER_MOORE);
2238 int n = subject.length(); 2313 int n = subject.length();
2239 int m = pattern.length(); 2314 int m = pattern.length();
2240 // Only preprocess at most kBMMaxShift last characters of pattern. 2315 // Only preprocess at most kBMMaxShift last characters of pattern.
2241 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift; 2316 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
2242 2317
2243 // Build the Good Suffix table and continue searching.
2244 BoyerMoorePopulateGoodSuffixTable(pattern, start);
2245 pchar last_char = pattern[m - 1]; 2318 pchar last_char = pattern[m - 1];
2246 // Continue search from i. 2319 // Continue search from i.
2247 while (idx <= n - m) { 2320 while (idx <= n - m) {
2248 int j = m - 1; 2321 int j = m - 1;
2249 schar c; 2322 schar c;
2250 while (last_char != (c = subject[idx + j])) { 2323 while (last_char != (c = subject[idx + j])) {
2251 int shift = j - CharOccurrence<schar, pchar>(c); 2324 int shift = j - CharOccurrence<schar, pchar>(c);
2252 idx += shift; 2325 idx += shift;
2253 if (idx > n - m) { 2326 if (idx > n - m) {
2254 return -1; 2327 return -1;
(...skipping 15 matching lines...) Expand all
2270 } 2343 }
2271 idx += shift; 2344 idx += shift;
2272 } 2345 }
2273 } 2346 }
2274 2347
2275 return -1; 2348 return -1;
2276 } 2349 }
2277 2350
2278 2351
2279 template <typename schar> 2352 template <typename schar>
2280 static int SingleCharIndexOf(Vector<const schar> string, 2353 static inline int SingleCharIndexOf(Vector<const schar> string,
2281 schar pattern_char, 2354 schar pattern_char,
2282 int start_index) { 2355 int start_index) {
2356 if (sizeof(schar) == 1) {
2357 const schar* pos = reinterpret_cast<const schar*>(
2358 memchr(string.start() + start_index,
2359 pattern_char,
2360 string.length() - start_index));
2361 if (pos == NULL) return -1;
2362 return pos - string.start();
2363 }
2283 for (int i = start_index, n = string.length(); i < n; i++) { 2364 for (int i = start_index, n = string.length(); i < n; i++) {
2284 if (pattern_char == string[i]) { 2365 if (pattern_char == string[i]) {
2285 return i; 2366 return i;
2286 } 2367 }
2287 } 2368 }
2288 return -1; 2369 return -1;
2289 } 2370 }
2290 2371
2291 2372
2292 template <typename schar> 2373 template <typename schar>
(...skipping 17 matching lines...) Expand all
2310 // does not occur at a position prior to the returned index. 2391 // does not occur at a position prior to the returned index.
2311 template <typename pchar, typename schar> 2392 template <typename pchar, typename schar>
2312 static int SimpleIndexOf(Vector<const schar> subject, 2393 static int SimpleIndexOf(Vector<const schar> subject,
2313 Vector<const pchar> pattern, 2394 Vector<const pchar> pattern,
2314 int idx, 2395 int idx,
2315 bool* complete) { 2396 bool* complete) {
2316 // Badness is a count of how much work we have done. When we have 2397 // Badness is a count of how much work we have done. When we have
2317 // done enough work we decide it's probably worth switching to a better 2398 // done enough work we decide it's probably worth switching to a better
2318 // algorithm. 2399 // algorithm.
2319 int badness = -10 - (pattern.length() << 2); 2400 int badness = -10 - (pattern.length() << 2);
2401
2320 // We know our pattern is at least 2 characters, we cache the first so 2402 // We know our pattern is at least 2 characters, we cache the first so
2321 // the common case of the first character not matching is faster. 2403 // the common case of the first character not matching is faster.
2322 pchar pattern_first_char = pattern[0]; 2404 pchar pattern_first_char = pattern[0];
2323
2324 for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) { 2405 for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
2325 badness++; 2406 badness++;
2326 if (badness > 0) { 2407 if (badness > 0) {
2327 *complete = false; 2408 *complete = false;
2328 return i; 2409 return i;
2329 } 2410 }
2330 if (subject[i] != pattern_first_char) continue; 2411 if (sizeof(schar) == 1 && sizeof(pchar) == 1) {
2412 const schar* pos = reinterpret_cast<const schar*>(
2413 memchr(subject.start() + i,
2414 pattern_first_char,
2415 n - i + 1));
2416 if (pos == NULL) {
2417 *complete = true;
2418 return -1;
2419 }
2420 i = pos - subject.start();
2421 } else {
2422 if (subject[i] != pattern_first_char) continue;
2423 }
2331 int j = 1; 2424 int j = 1;
2332 do { 2425 do {
2333 if (pattern[j] != subject[i+j]) { 2426 if (pattern[j] != subject[i+j]) {
2334 break; 2427 break;
2335 } 2428 }
2336 j++; 2429 j++;
2337 } while (j < pattern.length()); 2430 } while (j < pattern.length());
2338 if (j == pattern.length()) { 2431 if (j == pattern.length()) {
2339 *complete = true; 2432 *complete = true;
2340 return i; 2433 return i;
2341 } 2434 }
2342 badness += j; 2435 badness += j;
2343 } 2436 }
2344 *complete = true; 2437 *complete = true;
2345 return -1; 2438 return -1;
2346 } 2439 }
2347 2440
2348 // Simple indexOf that never bails out. For short patterns only. 2441 // Simple indexOf that never bails out. For short patterns only.
2349 template <typename pchar, typename schar> 2442 template <typename pchar, typename schar>
2350 static int SimpleIndexOf(Vector<const schar> subject, 2443 static int SimpleIndexOf(Vector<const schar> subject,
2351 Vector<const pchar> pattern, 2444 Vector<const pchar> pattern,
2352 int idx) { 2445 int idx) {
2353 pchar pattern_first_char = pattern[0]; 2446 pchar pattern_first_char = pattern[0];
2354 for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) { 2447 for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
2355 if (subject[i] != pattern_first_char) continue; 2448 if (sizeof(schar) == 1 && sizeof(pchar) == 1) {
2449 const schar* pos = reinterpret_cast<const schar*>(
2450 memchr(subject.start() + i,
2451 pattern_first_char,
2452 n - i + 1));
2453 if (pos == NULL) return -1;
2454 i = pos - subject.start();
2455 } else {
2456 if (subject[i] != pattern_first_char) continue;
2457 }
2356 int j = 1; 2458 int j = 1;
2357 do { 2459 do {
2358 if (pattern[j] != subject[i+j]) { 2460 if (pattern[j] != subject[i+j]) {
2359 break; 2461 break;
2360 } 2462 }
2361 j++; 2463 j++;
2362 } while (j < pattern.length()); 2464 } while (j < pattern.length());
2363 if (j == pattern.length()) { 2465 if (j == pattern.length()) {
2364 return i; 2466 return i;
2365 } 2467 }
2366 } 2468 }
2367 return -1; 2469 return -1;
2368 } 2470 }
2369 2471
2370 2472
2371 // Dispatch to different algorithms. 2473 // Strategy for searching for a string in another string.
2372 template <typename schar, typename pchar> 2474 enum StringSearchStrategy { SEARCH_FAIL, SEARCH_SHORT, SEARCH_LONG };
2373 static int StringMatchStrategy(Vector<const schar> sub, 2475
2374 Vector<const pchar> pat, 2476
2375 int start_index) { 2477 template <typename pchar>
2478 static inline StringSearchStrategy InitializeStringSearch(
2479 Vector<const pchar> pat, bool ascii_subject) {
2376 ASSERT(pat.length() > 1); 2480 ASSERT(pat.length() > 1);
2377
2378 // We have an ASCII haystack and a non-ASCII needle. Check if there 2481 // We have an ASCII haystack and a non-ASCII needle. Check if there
2379 // really is a non-ASCII character in the needle and bail out if there 2482 // really is a non-ASCII character in the needle and bail out if there
2380 // is. 2483 // is.
2381 if (sizeof(schar) == 1 && sizeof(pchar) > 1) { 2484 if (ascii_subject && sizeof(pchar) > 1) {
2382 for (int i = 0; i < pat.length(); i++) { 2485 for (int i = 0; i < pat.length(); i++) {
2383 uc16 c = pat[i]; 2486 uc16 c = pat[i];
2384 if (c > String::kMaxAsciiCharCode) { 2487 if (c > String::kMaxAsciiCharCode) {
2385 return -1; 2488 return SEARCH_FAIL;
2386 } 2489 }
2387 } 2490 }
2388 } 2491 }
2389 if (pat.length() < kBMMinPatternLength) { 2492 if (pat.length() < kBMMinPatternLength) {
2390 // We don't believe fancy searching can ever be more efficient. 2493 return SEARCH_SHORT;
2391 // The max shift of Boyer-Moore on a pattern of this length does
2392 // not compensate for the overhead.
2393 return SimpleIndexOf(sub, pat, start_index);
2394 } 2494 }
2495 algorithm = SIMPLE_SEARCH;
2496 return SEARCH_LONG;
2497 }
2498
2499
2500 // Dispatch long needle searches to different algorithms.
2501 template <typename schar, typename pchar>
2502 static int ComplexIndexOf(Vector<const schar> sub,
2503 Vector<const pchar> pat,
2504 int start_index) {
2505 ASSERT(pat.length() >= kBMMinPatternLength);
2395 // Try algorithms in order of increasing setup cost and expected performance. 2506 // Try algorithms in order of increasing setup cost and expected performance.
2396 bool complete; 2507 bool complete;
2397 int idx = SimpleIndexOf(sub, pat, start_index, &complete); 2508 int idx = start_index;
2398 if (complete) return idx; 2509 switch (algorithm) {
2399 idx = BoyerMooreHorspool(sub, pat, idx, &complete); 2510 case SIMPLE_SEARCH:
2400 if (complete) return idx; 2511 idx = SimpleIndexOf(sub, pat, idx, &complete);
2401 return BoyerMooreIndexOf(sub, pat, idx); 2512 if (complete) return idx;
2513 BoyerMoorePopulateBadCharTable(pat);
2514 algorithm = BOYER_MOORE_HORSPOOL;
2515 // FALLTHROUGH.
2516 case BOYER_MOORE_HORSPOOL:
2517 idx = BoyerMooreHorspool(sub, pat, idx, &complete);
2518 if (complete) return idx;
2519 // Build the Good Suffix table and continue searching.
2520 BoyerMoorePopulateGoodSuffixTable(pat);
2521 algorithm = BOYER_MOORE;
2522 // FALLTHROUGH.
2523 case BOYER_MOORE:
2524 return BoyerMooreIndexOf(sub, pat, idx);
2525 }
2526 UNREACHABLE();
2527 return -1;
2402 } 2528 }
2403 2529
2530
2531 // Dispatch to different search strategies for a single search.
2532 // If searching multiple times on the same needle, the search
2533 // strategy should only be computed once and then dispatch to different
2534 // loops.
2535 template <typename schar, typename pchar>
2536 static int StringSearch(Vector<const schar> sub,
2537 Vector<const pchar> pat,
2538 int start_index) {
2539 bool ascii_subject = (sizeof(schar) == 1);
2540 StringSearchStrategy strategy = InitializeStringSearch(pat, ascii_subject);
2541 switch (strategy) {
2542 case SEARCH_FAIL: return -1;
2543 case SEARCH_SHORT: return SimpleIndexOf(sub, pat, start_index);
2544 case SEARCH_LONG: return ComplexIndexOf(sub, pat, start_index);
2545 }
2546 UNREACHABLE();
2547 return -1;
2548 }
2549
2550
2404 // Perform string match of pattern on subject, starting at start index. 2551 // Perform string match of pattern on subject, starting at start index.
2405 // Caller must ensure that 0 <= start_index <= sub->length(), 2552 // Caller must ensure that 0 <= start_index <= sub->length(),
2406 // and should check that pat->length() + start_index <= sub->length() 2553 // and should check that pat->length() + start_index <= sub->length()
2407 int Runtime::StringMatch(Handle<String> sub, 2554 int Runtime::StringMatch(Handle<String> sub,
2408 Handle<String> pat, 2555 Handle<String> pat,
2409 int start_index) { 2556 int start_index) {
2410 ASSERT(0 <= start_index); 2557 ASSERT(0 <= start_index);
2411 ASSERT(start_index <= sub->length()); 2558 ASSERT(start_index <= sub->length());
2412 2559
2413 int pattern_length = pat->length(); 2560 int pattern_length = pat->length();
2414 if (pattern_length == 0) return start_index; 2561 if (pattern_length == 0) return start_index;
2415 2562
2416 int subject_length = sub->length(); 2563 int subject_length = sub->length();
2417 if (start_index + pattern_length > subject_length) return -1; 2564 if (start_index + pattern_length > subject_length) return -1;
2418 2565
2419 if (!sub->IsFlat()) { 2566 if (!sub->IsFlat()) {
2420 FlattenString(sub); 2567 FlattenString(sub);
2421 } 2568 }
2569
2422 // Searching for one specific character is common. For one 2570 // Searching for one specific character is common. For one
2423 // character patterns linear search is necessary, so any smart 2571 // character patterns linear search is necessary, so any smart
2424 // algorithm is unnecessary overhead. 2572 // algorithm is unnecessary overhead.
2425 if (pattern_length == 1) { 2573 if (pattern_length == 1) {
2426 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 2574 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
2427 if (sub->IsAsciiRepresentation()) { 2575 if (sub->IsAsciiRepresentation()) {
2428 uc16 pchar = pat->Get(0); 2576 uc16 pchar = pat->Get(0);
2429 if (pchar > String::kMaxAsciiCharCode) { 2577 if (pchar > String::kMaxAsciiCharCode) {
2430 return -1; 2578 return -1;
2431 } 2579 }
(...skipping 13 matching lines...) Expand all
2445 2593
2446 if (!pat->IsFlat()) { 2594 if (!pat->IsFlat()) {
2447 FlattenString(pat); 2595 FlattenString(pat);
2448 } 2596 }
2449 2597
2450 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 2598 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
2451 // dispatch on type of strings 2599 // dispatch on type of strings
2452 if (pat->IsAsciiRepresentation()) { 2600 if (pat->IsAsciiRepresentation()) {
2453 Vector<const char> pat_vector = pat->ToAsciiVector(); 2601 Vector<const char> pat_vector = pat->ToAsciiVector();
2454 if (sub->IsAsciiRepresentation()) { 2602 if (sub->IsAsciiRepresentation()) {
2455 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); 2603 return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
2456 } 2604 }
2457 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); 2605 return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
2458 } 2606 }
2459 Vector<const uc16> pat_vector = pat->ToUC16Vector(); 2607 Vector<const uc16> pat_vector = pat->ToUC16Vector();
2460 if (sub->IsAsciiRepresentation()) { 2608 if (sub->IsAsciiRepresentation()) {
2461 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); 2609 return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
2462 } 2610 }
2463 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); 2611 return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
2464 } 2612 }
2465 2613
2466 2614
2467 static Object* Runtime_StringIndexOf(Arguments args) { 2615 static Object* Runtime_StringIndexOf(Arguments args) {
2468 HandleScope scope; // create a new handle scope 2616 HandleScope scope; // create a new handle scope
2469 ASSERT(args.length() == 3); 2617 ASSERT(args.length() == 3);
2470 2618
2471 CONVERT_ARG_CHECKED(String, sub, 0); 2619 CONVERT_ARG_CHECKED(String, sub, 0);
2472 CONVERT_ARG_CHECKED(String, pat, 1); 2620 CONVERT_ARG_CHECKED(String, pat, 1);
2473 2621
(...skipping 1734 matching lines...) Expand 10 before | Expand all | Expand 10 after
4208 int right = length; 4356 int right = length;
4209 if (trimRight) { 4357 if (trimRight) {
4210 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) { 4358 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
4211 right--; 4359 right--;
4212 } 4360 }
4213 } 4361 }
4214 return s->SubString(left, right); 4362 return s->SubString(left, right);
4215 } 4363 }
4216 4364
4217 4365
4366 template <typename schar, typename pchar>
4367 void FindStringIndices(Vector<const schar> subject,
4368 Vector<const pchar> pattern,
4369 ZoneList<int>* indices,
4370 unsigned int limit) {
4371 ASSERT(limit > 0);
4372 // Collect indices of pattern in subject, and the end-of-string index.
4373 // Stop after finding at most limit values.
4374 StringSearchStrategy strategy =
4375 InitializeStringSearch(pattern, sizeof(schar) == 1);
4376 switch (strategy) {
4377 case SEARCH_FAIL: return;
4378 case SEARCH_SHORT: {
4379 int pattern_length = pattern.length();
4380 int index = 0;
4381 while (limit > 0) {
4382 index = SimpleIndexOf(subject, pattern, index);
4383 if (index < 0) return;
4384 indices->Add(index);
4385 index += pattern_length;
4386 limit--;
4387 }
4388 return;
4389 }
4390 case SEARCH_LONG: {
4391 int pattern_length = pattern.length();
4392 int index = 0;
4393 while (limit > 0) {
4394 index = ComplexIndexOf(subject, pattern, index);
4395 if (index < 0) return;
4396 indices->Add(index);
4397 index += pattern_length;
4398 limit--;
4399 }
4400 return;
4401 }
4402 default:
4403 UNREACHABLE();
4404 return;
4405 }
4406 }
4407
4408 template <typename schar>
4409 inline void FindCharIndices(Vector<const schar> subject,
4410 const schar pattern_char,
4411 ZoneList<int>* indices,
4412 unsigned int limit) {
4413 // Collect indices of pattern_char in subject, and the end-of-string index.
4414 // Stop after finding at most limit values.
4415 int index = 0;
4416 while (limit > 0) {
4417 index = SingleCharIndexOf(subject, pattern_char, index);
4418 if (index < 0) return;
4419 indices->Add(index);
4420 index++;
4421 limit--;
4422 }
4423 }
4424
4425
4426 static Object* Runtime_StringSplit(Arguments args) {
4427 ASSERT(args.length() == 3);
4428 HandleScope handle_scope;
4429 CONVERT_ARG_CHECKED(String, subject, 0);
4430 CONVERT_ARG_CHECKED(String, pattern, 1);
4431 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
4432
4433 int subject_length = subject->length();
4434 int pattern_length = pattern->length();
4435 RUNTIME_ASSERT(pattern_length > 0);
4436
4437 // The limit can be very large (0xffffffffu), but since the pattern
4438 // isn't empty, we can never create more parts than ~half the length
4439 // of the subject.
4440
4441 if (!subject->IsFlat()) FlattenString(subject);
4442
4443 static const int kMaxInitialListCapacity = 16;
4444
4445 ZoneScope scope(DELETE_ON_EXIT);
4446
4447 // Find (up to limit) indices of separator and end-of-string in subject
4448 int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
4449 ZoneList<int> indices(initial_capacity);
4450 if (pattern_length == 1) {
4451 // Special case, go directly to fast single-character split.
4452 AssertNoAllocation nogc;
4453 uc16 pattern_char = pattern->Get(0);
4454 if (subject->IsTwoByteRepresentation()) {
4455 FindCharIndices(subject->ToUC16Vector(), pattern_char,
4456 &indices,
4457 limit);
4458 } else if (pattern_char <= String::kMaxAsciiCharCode) {
4459 FindCharIndices(subject->ToAsciiVector(),
4460 static_cast<char>(pattern_char),
4461 &indices,
4462 limit);
4463 }
4464 } else {
4465 if (!pattern->IsFlat()) FlattenString(pattern);
4466 AssertNoAllocation nogc;
4467 if (subject->IsAsciiRepresentation()) {
4468 Vector<const char> subject_vector = subject->ToAsciiVector();
4469 if (pattern->IsAsciiRepresentation()) {
4470 FindStringIndices(subject_vector,
4471 pattern->ToAsciiVector(),
4472 &indices,
4473 limit);
4474 } else {
4475 FindStringIndices(subject_vector,
4476 pattern->ToUC16Vector(),
4477 &indices,
4478 limit);
4479 }
4480 } else {
4481 Vector<const uc16> subject_vector = subject->ToUC16Vector();
4482 if (pattern->IsAsciiRepresentation()) {
4483 FindStringIndices(subject_vector,
4484 pattern->ToAsciiVector(),
4485 &indices,
4486 limit);
4487 } else {
4488 FindStringIndices(subject_vector,
4489 pattern->ToUC16Vector(),
4490 &indices,
4491 limit);
4492 }
4493 }
4494 }
4495 if (static_cast<uint32_t>(indices.length()) < limit) {
4496 indices.Add(subject_length);
4497 }
4498 // The list indices now contains the end of each part to create.
4499
4500
4501 // Create JSArray of substrings separated by separator.
4502 int part_count = indices.length();
4503
4504 Handle<JSArray> result = Factory::NewJSArray(part_count);
4505 result->set_length(Smi::FromInt(part_count));
4506
4507 ASSERT(result->HasFastElements());
4508
4509 if (part_count == 1 && indices.at(0) == subject_length) {
4510 FixedArray::cast(result->elements())->set(0, *subject);
4511 return *result;
4512 }
4513
4514 Handle<FixedArray> elements(FixedArray::cast(result->elements()));
4515 int part_start = 0;
4516 for (int i = 0; i < part_count; i++) {
4517 HandleScope local_loop_handle;
4518 int part_end = indices.at(i);
4519 Handle<String> substring =
4520 Factory::NewSubString(subject, part_start, part_end);
4521 elements->set(i, *substring);
4522 part_start = part_end + pattern_length;
4523 }
4524
4525 return *result;
4526 }
4527
4528
4218 // Copies ascii characters to the given fixed array looking up 4529 // Copies ascii characters to the given fixed array looking up
4219 // one-char strings in the cache. Gives up on the first char that is 4530 // one-char strings in the cache. Gives up on the first char that is
4220 // not in the cache and fills the remainder with smi zeros. Returns 4531 // not in the cache and fills the remainder with smi zeros. Returns
4221 // the length of the successfully copied prefix. 4532 // the length of the successfully copied prefix.
4222 static int CopyCachedAsciiCharsToArray(const char* chars, 4533 static int CopyCachedAsciiCharsToArray(const char* chars,
4223 FixedArray* elements, 4534 FixedArray* elements,
4224 int length) { 4535 int length) {
4225 AssertNoAllocation nogc; 4536 AssertNoAllocation nogc;
4226 FixedArray* ascii_cache = Heap::single_character_string_cache(); 4537 FixedArray* ascii_cache = Heap::single_character_string_cache();
4227 Object* undefined = Heap::undefined_value(); 4538 Object* undefined = Heap::undefined_value();
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
4784 prefix_length = y->length(); 5095 prefix_length = y->length();
4785 equal_prefix_result = Smi::FromInt(GREATER); 5096 equal_prefix_result = Smi::FromInt(GREATER);
4786 } else if (y->length() > prefix_length) { 5097 } else if (y->length() > prefix_length) {
4787 equal_prefix_result = Smi::FromInt(LESS); 5098 equal_prefix_result = Smi::FromInt(LESS);
4788 } 5099 }
4789 int r; 5100 int r;
4790 if (x->IsAsciiRepresentation()) { 5101 if (x->IsAsciiRepresentation()) {
4791 Vector<const char> x_chars = x->ToAsciiVector(); 5102 Vector<const char> x_chars = x->ToAsciiVector();
4792 if (y->IsAsciiRepresentation()) { 5103 if (y->IsAsciiRepresentation()) {
4793 Vector<const char> y_chars = y->ToAsciiVector(); 5104 Vector<const char> y_chars = y->ToAsciiVector();
4794 r = memcmp(x_chars.start(), y_chars.start(), prefix_length); 5105 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
4795 } else { 5106 } else {
4796 Vector<const uc16> y_chars = y->ToUC16Vector(); 5107 Vector<const uc16> y_chars = y->ToUC16Vector();
4797 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); 5108 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
4798 } 5109 }
4799 } else { 5110 } else {
4800 Vector<const uc16> x_chars = x->ToUC16Vector(); 5111 Vector<const uc16> x_chars = x->ToUC16Vector();
4801 if (y->IsAsciiRepresentation()) { 5112 if (y->IsAsciiRepresentation()) {
4802 Vector<const char> y_chars = y->ToAsciiVector(); 5113 Vector<const char> y_chars = y->ToAsciiVector();
4803 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); 5114 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
4804 } else { 5115 } else {
(...skipping 27 matching lines...) Expand all
4832 if (x->length() == 0) return Smi::FromInt(EQUAL); 5143 if (x->length() == 0) return Smi::FromInt(EQUAL);
4833 return Smi::FromInt(GREATER); 5144 return Smi::FromInt(GREATER);
4834 } else if (x->length() == 0) { 5145 } else if (x->length() == 0) {
4835 return Smi::FromInt(LESS); 5146 return Smi::FromInt(LESS);
4836 } 5147 }
4837 5148
4838 int d = x->Get(0) - y->Get(0); 5149 int d = x->Get(0) - y->Get(0);
4839 if (d < 0) return Smi::FromInt(LESS); 5150 if (d < 0) return Smi::FromInt(LESS);
4840 else if (d > 0) return Smi::FromInt(GREATER); 5151 else if (d > 0) return Smi::FromInt(GREATER);
4841 5152
4842 x->TryFlatten(); 5153 Object* obj = Heap::PrepareForCompare(x);
4843 y->TryFlatten(); 5154 if (obj->IsFailure()) return obj;
5155 obj = Heap::PrepareForCompare(y);
5156 if (obj->IsFailure()) return obj;
4844 5157
4845 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y) 5158 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
4846 : StringInputBufferCompare(x, y); 5159 : StringInputBufferCompare(x, y);
4847 } 5160 }
4848 5161
4849 5162
4850 static Object* Runtime_Math_abs(Arguments args) {
4851 NoHandleAllocation ha;
4852 ASSERT(args.length() == 1);
4853 Counters::math_abs.Increment();
4854
4855 CONVERT_DOUBLE_CHECKED(x, args[0]);
4856 return Heap::AllocateHeapNumber(fabs(x));
4857 }
4858
4859
4860 static Object* Runtime_Math_acos(Arguments args) { 5163 static Object* Runtime_Math_acos(Arguments args) {
4861 NoHandleAllocation ha; 5164 NoHandleAllocation ha;
4862 ASSERT(args.length() == 1); 5165 ASSERT(args.length() == 1);
4863 Counters::math_acos.Increment(); 5166 Counters::math_acos.Increment();
4864 5167
4865 CONVERT_DOUBLE_CHECKED(x, args[0]); 5168 CONVERT_DOUBLE_CHECKED(x, args[0]);
4866 return TranscendentalCache::Get(TranscendentalCache::ACOS, x); 5169 return TranscendentalCache::Get(TranscendentalCache::ACOS, x);
4867 } 5170 }
4868 5171
4869 5172
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
5040 if (y == 0) { 5343 if (y == 0) {
5041 return Smi::FromInt(1); 5344 return Smi::FromInt(1);
5042 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { 5345 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
5043 return Heap::nan_value(); 5346 return Heap::nan_value();
5044 } else { 5347 } else {
5045 return Heap::AllocateHeapNumber(pow(x, y)); 5348 return Heap::AllocateHeapNumber(pow(x, y));
5046 } 5349 }
5047 } 5350 }
5048 5351
5049 5352
5050 static Object* Runtime_Math_round(Arguments args) { 5353 static Object* Runtime_RoundNumber(Arguments args) {
5051 NoHandleAllocation ha; 5354 NoHandleAllocation ha;
5052 ASSERT(args.length() == 1); 5355 ASSERT(args.length() == 1);
5053 Counters::math_round.Increment(); 5356 Counters::math_round.Increment();
5054 5357
5055 CONVERT_DOUBLE_CHECKED(x, args[0]); 5358 if (!args[0]->IsHeapNumber()) {
5056 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value(); 5359 // Must be smi. Return the argument unchanged for all the other types
5057 double integer = ceil(x); 5360 // to make fuzz-natives test happy.
5058 if (integer - x > 0.5) { integer -= 1.0; } 5361 return args[0];
5059 return Heap::NumberFromDouble(integer); 5362 }
5363
5364 HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
5365
5366 double value = number->value();
5367 int exponent = number->get_exponent();
5368 int sign = number->get_sign();
5369
5370 // We compare with kSmiValueSize - 3 because (2^30 - 0.1) has exponent 29 and
5371 // should be rounded to 2^30, which is not smi.
5372 if (!sign && exponent <= kSmiValueSize - 3) {
5373 return Smi::FromInt(static_cast<int>(value + 0.5));
5374 }
5375
5376 // If the magnitude is big enough, there's no place for fraction part. If we
5377 // try to add 0.5 to this number, 1.0 will be added instead.
5378 if (exponent >= 52) {
5379 return number;
5380 }
5381
5382 if (sign && value >= -0.5) return Heap::minus_zero_value();
5383
5384 return Heap::NumberFromDouble(floor(value + 0.5));
5060 } 5385 }
5061 5386
5062 5387
5063 static Object* Runtime_Math_sin(Arguments args) { 5388 static Object* Runtime_Math_sin(Arguments args) {
5064 NoHandleAllocation ha; 5389 NoHandleAllocation ha;
5065 ASSERT(args.length() == 1); 5390 ASSERT(args.length() == 1);
5066 Counters::math_sin.Increment(); 5391 Counters::math_sin.Increment();
5067 5392
5068 CONVERT_DOUBLE_CHECKED(x, args[0]); 5393 CONVERT_DOUBLE_CHECKED(x, args[0]);
5069 return TranscendentalCache::Get(TranscendentalCache::SIN, x); 5394 return TranscendentalCache::Get(TranscendentalCache::SIN, x);
(...skipping 13 matching lines...) Expand all
5083 static Object* Runtime_Math_tan(Arguments args) { 5408 static Object* Runtime_Math_tan(Arguments args) {
5084 NoHandleAllocation ha; 5409 NoHandleAllocation ha;
5085 ASSERT(args.length() == 1); 5410 ASSERT(args.length() == 1);
5086 Counters::math_tan.Increment(); 5411 Counters::math_tan.Increment();
5087 5412
5088 CONVERT_DOUBLE_CHECKED(x, args[0]); 5413 CONVERT_DOUBLE_CHECKED(x, args[0]);
5089 return TranscendentalCache::Get(TranscendentalCache::TAN, x); 5414 return TranscendentalCache::Get(TranscendentalCache::TAN, x);
5090 } 5415 }
5091 5416
5092 5417
5093 static Object* Runtime_DateMakeDay(Arguments args) { 5418 static int MakeDay(int year, int month, int day) {
5094 NoHandleAllocation ha;
5095 ASSERT(args.length() == 3);
5096
5097 CONVERT_SMI_CHECKED(year, args[0]);
5098 CONVERT_SMI_CHECKED(month, args[1]);
5099 CONVERT_SMI_CHECKED(date, args[2]);
5100
5101 static const int day_from_month[] = {0, 31, 59, 90, 120, 151, 5419 static const int day_from_month[] = {0, 31, 59, 90, 120, 151,
5102 181, 212, 243, 273, 304, 334}; 5420 181, 212, 243, 273, 304, 334};
5103 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152, 5421 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152,
5104 182, 213, 244, 274, 305, 335}; 5422 182, 213, 244, 274, 305, 335};
5105 5423
5106 year += month / 12; 5424 year += month / 12;
5107 month %= 12; 5425 month %= 12;
5108 if (month < 0) { 5426 if (month < 0) {
5109 year--; 5427 year--;
5110 month += 12; 5428 month += 12;
5111 } 5429 }
5112 5430
5113 ASSERT(month >= 0); 5431 ASSERT(month >= 0);
5114 ASSERT(month < 12); 5432 ASSERT(month < 12);
5115 5433
5116 // year_delta is an arbitrary number such that: 5434 // year_delta is an arbitrary number such that:
5117 // a) year_delta = -1 (mod 400) 5435 // a) year_delta = -1 (mod 400)
5118 // b) year + year_delta > 0 for years in the range defined by 5436 // b) year + year_delta > 0 for years in the range defined by
5119 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of 5437 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
5120 // Jan 1 1970. This is required so that we don't run into integer 5438 // Jan 1 1970. This is required so that we don't run into integer
5121 // division of negative numbers. 5439 // division of negative numbers.
5122 // c) there shouldn't be overflow for 32-bit integers in the following 5440 // c) there shouldn't be an overflow for 32-bit integers in the following
5123 // operations. 5441 // operations.
5124 static const int year_delta = 399999; 5442 static const int year_delta = 399999;
5125 static const int base_day = 365 * (1970 + year_delta) + 5443 static const int base_day = 365 * (1970 + year_delta) +
5126 (1970 + year_delta) / 4 - 5444 (1970 + year_delta) / 4 -
5127 (1970 + year_delta) / 100 + 5445 (1970 + year_delta) / 100 +
5128 (1970 + year_delta) / 400; 5446 (1970 + year_delta) / 400;
5129 5447
5130 int year1 = year + year_delta; 5448 int year1 = year + year_delta;
5131 int day_from_year = 365 * year1 + 5449 int day_from_year = 365 * year1 +
5132 year1 / 4 - 5450 year1 / 4 -
5133 year1 / 100 + 5451 year1 / 100 +
5134 year1 / 400 - 5452 year1 / 400 -
5135 base_day; 5453 base_day;
5136 5454
5137 if (year % 4 || (year % 100 == 0 && year % 400 != 0)) { 5455 if (year % 4 || (year % 100 == 0 && year % 400 != 0)) {
5138 return Smi::FromInt(day_from_year + day_from_month[month] + date - 1); 5456 return day_from_year + day_from_month[month] + day - 1;
5139 } 5457 }
5140 5458
5141 return Smi::FromInt(day_from_year + day_from_month_leap[month] + date - 1); 5459 return day_from_year + day_from_month_leap[month] + day - 1;
5460 }
5461
5462
5463 static Object* Runtime_DateMakeDay(Arguments args) {
5464 NoHandleAllocation ha;
5465 ASSERT(args.length() == 3);
5466
5467 CONVERT_SMI_CHECKED(year, args[0]);
5468 CONVERT_SMI_CHECKED(month, args[1]);
5469 CONVERT_SMI_CHECKED(date, args[2]);
5470
5471 return Smi::FromInt(MakeDay(year, month, date));
5472 }
5473
5474
5475 static const int kDays4Years[] = {0, 365, 2 * 365, 3 * 365 + 1};
5476 static const int kDaysIn4Years = 4 * 365 + 1;
5477 static const int kDaysIn100Years = 25 * kDaysIn4Years - 1;
5478 static const int kDaysIn400Years = 4 * kDaysIn100Years + 1;
5479 static const int kDays1970to2000 = 30 * 365 + 7;
5480 static const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years -
5481 kDays1970to2000;
5482 static const int kYearsOffset = 400000;
5483
5484 static const char kDayInYear[] = {
5485 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5486 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5487 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5488 22, 23, 24, 25, 26, 27, 28,
5489 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5490 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5491 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5492 22, 23, 24, 25, 26, 27, 28, 29, 30,
5493 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5494 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5495 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5496 22, 23, 24, 25, 26, 27, 28, 29, 30,
5497 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5498 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5499 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5500 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5501 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5502 22, 23, 24, 25, 26, 27, 28, 29, 30,
5503 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5504 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5505 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5506 22, 23, 24, 25, 26, 27, 28, 29, 30,
5507 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5508 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5509
5510 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5511 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5512 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5513 22, 23, 24, 25, 26, 27, 28,
5514 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5515 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5516 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5517 22, 23, 24, 25, 26, 27, 28, 29, 30,
5518 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5519 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5520 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5521 22, 23, 24, 25, 26, 27, 28, 29, 30,
5522 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5523 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5524 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5525 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5526 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5527 22, 23, 24, 25, 26, 27, 28, 29, 30,
5528 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5529 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5530 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5531 22, 23, 24, 25, 26, 27, 28, 29, 30,
5532 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5533 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5534
5535 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5536 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5537 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5538 22, 23, 24, 25, 26, 27, 28, 29,
5539 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5540 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5541 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5542 22, 23, 24, 25, 26, 27, 28, 29, 30,
5543 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5544 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5545 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5546 22, 23, 24, 25, 26, 27, 28, 29, 30,
5547 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5548 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5549 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5550 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5551 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5552 22, 23, 24, 25, 26, 27, 28, 29, 30,
5553 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5554 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5555 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5556 22, 23, 24, 25, 26, 27, 28, 29, 30,
5557 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5558 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5559
5560 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5561 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5562 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5563 22, 23, 24, 25, 26, 27, 28,
5564 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5565 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5566 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5567 22, 23, 24, 25, 26, 27, 28, 29, 30,
5568 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5569 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5570 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5571 22, 23, 24, 25, 26, 27, 28, 29, 30,
5572 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5573 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5574 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5575 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5576 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5577 22, 23, 24, 25, 26, 27, 28, 29, 30,
5578 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5579 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
5580 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5581 22, 23, 24, 25, 26, 27, 28, 29, 30,
5582 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
5583 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
5584
5585 static const char kMonthInYear[] = {
5586 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5587 0, 0, 0, 0, 0, 0,
5588 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5589 1, 1, 1,
5590 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5591 2, 2, 2, 2, 2, 2,
5592 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5593 3, 3, 3, 3, 3,
5594 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5595 4, 4, 4, 4, 4, 4,
5596 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5597 5, 5, 5, 5, 5,
5598 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
5599 6, 6, 6, 6, 6, 6,
5600 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
5601 7, 7, 7, 7, 7, 7,
5602 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
5603 8, 8, 8, 8, 8,
5604 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
5605 9, 9, 9, 9, 9, 9,
5606 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
5607 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
5608 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
5609 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
5610
5611 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5612 0, 0, 0, 0, 0, 0,
5613 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5614 1, 1, 1,
5615 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5616 2, 2, 2, 2, 2, 2,
5617 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5618 3, 3, 3, 3, 3,
5619 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5620 4, 4, 4, 4, 4, 4,
5621 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5622 5, 5, 5, 5, 5,
5623 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
5624 6, 6, 6, 6, 6, 6,
5625 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
5626 7, 7, 7, 7, 7, 7,
5627 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
5628 8, 8, 8, 8, 8,
5629 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
5630 9, 9, 9, 9, 9, 9,
5631 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
5632 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
5633 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
5634 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
5635
5636 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5637 0, 0, 0, 0, 0, 0,
5638 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5639 1, 1, 1, 1,
5640 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5641 2, 2, 2, 2, 2, 2,
5642 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5643 3, 3, 3, 3, 3,
5644 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5645 4, 4, 4, 4, 4, 4,
5646 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5647 5, 5, 5, 5, 5,
5648 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
5649 6, 6, 6, 6, 6, 6,
5650 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
5651 7, 7, 7, 7, 7, 7,
5652 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
5653 8, 8, 8, 8, 8,
5654 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
5655 9, 9, 9, 9, 9, 9,
5656 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
5657 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
5658 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
5659 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
5660
5661 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5662 0, 0, 0, 0, 0, 0,
5663 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5664 1, 1, 1,
5665 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5666 2, 2, 2, 2, 2, 2,
5667 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5668 3, 3, 3, 3, 3,
5669 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5670 4, 4, 4, 4, 4, 4,
5671 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5672 5, 5, 5, 5, 5,
5673 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
5674 6, 6, 6, 6, 6, 6,
5675 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
5676 7, 7, 7, 7, 7, 7,
5677 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
5678 8, 8, 8, 8, 8,
5679 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
5680 9, 9, 9, 9, 9, 9,
5681 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
5682 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
5683 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
5684 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11};
5685
5686
5687 // This function works for dates from 1970 to 2099.
5688 static inline void DateYMDFromTimeAfter1970(int date,
5689 int& year, int& month, int& day) {
5690 #ifdef DEBUG
5691 int save_date = date; // Need this for ASSERT in the end.
5692 #endif
5693
5694 year = 1970 + (4 * date + 2) / kDaysIn4Years;
5695 date %= kDaysIn4Years;
5696
5697 month = kMonthInYear[date];
5698 day = kDayInYear[date];
5699
5700 ASSERT(MakeDay(year, month, day) == save_date);
5701 }
5702
5703
5704 static inline void DateYMDFromTimeSlow(int date,
5705 int& year, int& month, int& day) {
5706 #ifdef DEBUG
5707 int save_date = date; // Need this for ASSERT in the end.
5708 #endif
5709
5710 date += kDaysOffset;
5711 year = 400 * (date / kDaysIn400Years) - kYearsOffset;
5712 date %= kDaysIn400Years;
5713
5714 ASSERT(MakeDay(year, 0, 1) + date == save_date);
5715
5716 date--;
5717 int yd1 = date / kDaysIn100Years;
5718 date %= kDaysIn100Years;
5719 year += 100 * yd1;
5720
5721 date++;
5722 int yd2 = date / kDaysIn4Years;
5723 date %= kDaysIn4Years;
5724 year += 4 * yd2;
5725
5726 date--;
5727 int yd3 = date / 365;
5728 date %= 365;
5729 year += yd3;
5730
5731 bool is_leap = (!yd1 || yd2) && !yd3;
5732
5733 ASSERT(date >= -1);
5734 ASSERT(is_leap || (date >= 0));
5735 ASSERT((date < 365) || (is_leap && (date < 366)));
5736 ASSERT(is_leap == ((year % 4 == 0) && (year % 100 || (year % 400 == 0))));
5737 ASSERT(is_leap || ((MakeDay(year, 0, 1) + date) == save_date));
5738 ASSERT(!is_leap || ((MakeDay(year, 0, 1) + date + 1) == save_date));
5739
5740 if (is_leap) {
5741 day = kDayInYear[2*365 + 1 + date];
5742 month = kMonthInYear[2*365 + 1 + date];
5743 } else {
5744 day = kDayInYear[date];
5745 month = kMonthInYear[date];
5746 }
5747
5748 ASSERT(MakeDay(year, month, day) == save_date);
5749 }
5750
5751
5752 static inline void DateYMDFromTime(int date,
5753 int& year, int& month, int& day) {
5754 if (date >= 0 && date < 32 * kDaysIn4Years) {
5755 DateYMDFromTimeAfter1970(date, year, month, day);
5756 } else {
5757 DateYMDFromTimeSlow(date, year, month, day);
5758 }
5759 }
5760
5761
5762 static Object* Runtime_DateYMDFromTime(Arguments args) {
5763 NoHandleAllocation ha;
5764 ASSERT(args.length() == 2);
5765
5766 CONVERT_DOUBLE_CHECKED(t, args[0]);
5767 CONVERT_CHECKED(JSArray, res_array, args[1]);
5768
5769 int year, month, day;
5770 DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day);
5771
5772 res_array->SetElement(0, Smi::FromInt(year));
5773 res_array->SetElement(1, Smi::FromInt(month));
5774 res_array->SetElement(2, Smi::FromInt(day));
5775
5776 return Heap::undefined_value();
5142 } 5777 }
5143 5778
5144 5779
5145 static Object* Runtime_NewArgumentsFast(Arguments args) { 5780 static Object* Runtime_NewArgumentsFast(Arguments args) {
5146 NoHandleAllocation ha; 5781 NoHandleAllocation ha;
5147 ASSERT(args.length() == 3); 5782 ASSERT(args.length() == 3);
5148 5783
5149 JSFunction* callee = JSFunction::cast(args[0]); 5784 JSFunction* callee = JSFunction::cast(args[0]);
5150 Object** parameters = reinterpret_cast<Object**>(args[1]); 5785 Object** parameters = reinterpret_cast<Object**>(args[1]);
5151 const int length = Smi::cast(args[2])->value(); 5786 const int length = Smi::cast(args[2])->value();
(...skipping 3322 matching lines...) Expand 10 before | Expand all | Expand 10 after
8474 SharedFunctionInfo::cast(wrapper->value())); 9109 SharedFunctionInfo::cast(wrapper->value()));
8475 LiveEdit::FunctionPatchabilityStatus check_res = 9110 LiveEdit::FunctionPatchabilityStatus check_res =
8476 FindFunctionCodeOnStacks(shared); 9111 FindFunctionCodeOnStacks(shared);
8477 SetElement(result, i, Handle<Smi>(Smi::FromInt(check_res))); 9112 SetElement(result, i, Handle<Smi>(Smi::FromInt(check_res)));
8478 } 9113 }
8479 9114
8480 return *result; 9115 return *result;
8481 } 9116 }
8482 9117
8483 9118
9119 // A testing entry. Returns statement position which is the closest to
9120 // source_position.
9121 static Object* Runtime_GetFunctionCodePositionFromSource(Arguments args) {
9122 ASSERT(args.length() == 2);
9123 HandleScope scope;
9124 CONVERT_ARG_CHECKED(JSFunction, function, 0);
9125 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
9126
9127 Handle<Code> code(function->code());
9128
9129 RelocIterator it(*code, 1 << RelocInfo::STATEMENT_POSITION);
9130 int closest_pc = 0;
9131 int distance = kMaxInt;
9132 while (!it.done()) {
9133 int statement_position = static_cast<int>(it.rinfo()->data());
9134 // Check if this break point is closer that what was previously found.
9135 if (source_position <= statement_position &&
9136 statement_position - source_position < distance) {
9137 closest_pc = it.rinfo()->pc() - code->instruction_start();
9138 distance = statement_position - source_position;
9139 // Check whether we can't get any closer.
9140 if (distance == 0) break;
9141 }
9142 it.next();
9143 }
9144
9145 return Smi::FromInt(closest_pc);
9146 }
9147
9148
8484 #endif // ENABLE_DEBUGGER_SUPPORT 9149 #endif // ENABLE_DEBUGGER_SUPPORT
8485 9150
8486 #ifdef ENABLE_LOGGING_AND_PROFILING 9151 #ifdef ENABLE_LOGGING_AND_PROFILING
8487 9152
8488 static Object* Runtime_ProfilerResume(Arguments args) { 9153 static Object* Runtime_ProfilerResume(Arguments args) {
8489 NoHandleAllocation ha; 9154 NoHandleAllocation ha;
8490 ASSERT(args.length() == 2); 9155 ASSERT(args.length() == 2);
8491 9156
8492 CONVERT_CHECKED(Smi, smi_modules, args[0]); 9157 CONVERT_CHECKED(Smi, smi_modules, args[0]);
8493 CONVERT_CHECKED(Smi, smi_tag, args[1]); 9158 CONVERT_CHECKED(Smi, smi_tag, args[1]);
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
8668 9333
8669 9334
8670 #ifdef DEBUG 9335 #ifdef DEBUG
8671 // ListNatives is ONLY used by the fuzz-natives.js in debug mode 9336 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
8672 // Exclude the code in release mode. 9337 // Exclude the code in release mode.
8673 static Object* Runtime_ListNatives(Arguments args) { 9338 static Object* Runtime_ListNatives(Arguments args) {
8674 ASSERT(args.length() == 0); 9339 ASSERT(args.length() == 0);
8675 HandleScope scope; 9340 HandleScope scope;
8676 Handle<JSArray> result = Factory::NewJSArray(0); 9341 Handle<JSArray> result = Factory::NewJSArray(0);
8677 int index = 0; 9342 int index = 0;
9343 bool inline_runtime_functions = false;
8678 #define ADD_ENTRY(Name, argc, ressize) \ 9344 #define ADD_ENTRY(Name, argc, ressize) \
8679 { \ 9345 { \
8680 HandleScope inner; \ 9346 HandleScope inner; \
8681 Handle<String> name = \ 9347 Handle<String> name; \
8682 Factory::NewStringFromAscii( \ 9348 /* Inline runtime functions have an underscore in front of the name. */ \
8683 Vector<const char>(#Name, StrLength(#Name))); \ 9349 if (inline_runtime_functions) { \
9350 name = Factory::NewStringFromAscii( \
9351 Vector<const char>("_" #Name, StrLength("_" #Name))); \
9352 } else { \
9353 name = Factory::NewStringFromAscii( \
9354 Vector<const char>(#Name, StrLength(#Name))); \
9355 } \
8684 Handle<JSArray> pair = Factory::NewJSArray(0); \ 9356 Handle<JSArray> pair = Factory::NewJSArray(0); \
8685 SetElement(pair, 0, name); \ 9357 SetElement(pair, 0, name); \
8686 SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \ 9358 SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \
8687 SetElement(result, index++, pair); \ 9359 SetElement(result, index++, pair); \
8688 } 9360 }
9361 inline_runtime_functions = false;
8689 RUNTIME_FUNCTION_LIST(ADD_ENTRY) 9362 RUNTIME_FUNCTION_LIST(ADD_ENTRY)
9363 inline_runtime_functions = true;
9364 INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
8690 #undef ADD_ENTRY 9365 #undef ADD_ENTRY
8691 return *result; 9366 return *result;
8692 } 9367 }
8693 #endif 9368 #endif
8694 9369
8695 9370
8696 static Object* Runtime_Log(Arguments args) { 9371 static Object* Runtime_Log(Arguments args) {
8697 ASSERT(args.length() == 2); 9372 ASSERT(args.length() == 2);
8698 CONVERT_CHECKED(String, format, args[0]); 9373 CONVERT_CHECKED(String, format, args[0]);
8699 CONVERT_CHECKED(JSArray, elms, args[1]); 9374 CONVERT_CHECKED(JSArray, elms, args[1]);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
8749 } else { 9424 } else {
8750 // Handle last resort GC and make sure to allow future allocations 9425 // Handle last resort GC and make sure to allow future allocations
8751 // to grow the heap without causing GCs (if possible). 9426 // to grow the heap without causing GCs (if possible).
8752 Counters::gc_last_resort_from_js.Increment(); 9427 Counters::gc_last_resort_from_js.Increment();
8753 Heap::CollectAllGarbage(false); 9428 Heap::CollectAllGarbage(false);
8754 } 9429 }
8755 } 9430 }
8756 9431
8757 9432
8758 } } // namespace v8::internal 9433 } } // namespace v8::internal
OLDNEW
« src/objects.h ('K') | « src/runtime.h ('k') | src/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698