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

Side by Side Diff: src/runtime.cc

Issue 7860035: Merge bleeding edge up to 9192 into the GC branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 3 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 | « src/runtime.h ('k') | src/runtime.js » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 "bootstrapper.h"
35 #include "codegen.h" 36 #include "codegen.h"
36 #include "compilation-cache.h" 37 #include "compilation-cache.h"
37 #include "compiler.h" 38 #include "compiler.h"
38 #include "cpu.h" 39 #include "cpu.h"
39 #include "dateparser-inl.h" 40 #include "dateparser-inl.h"
40 #include "debug.h" 41 #include "debug.h"
41 #include "deoptimizer.h" 42 #include "deoptimizer.h"
42 #include "execution.h" 43 #include "execution.h"
43 #include "global-handles.h" 44 #include "global-handles.h"
44 #include "jsregexp.h" 45 #include "jsregexp.h"
(...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 Handle<Object> type_handle = 1143 Handle<Object> type_handle =
1143 isolate->factory()->NewStringFromAscii(CStrVector(type)); 1144 isolate->factory()->NewStringFromAscii(CStrVector(type));
1144 Handle<Object> args[2] = { type_handle, name }; 1145 Handle<Object> args[2] = { type_handle, name };
1145 Handle<Object> error = 1146 Handle<Object> error =
1146 isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2)); 1147 isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
1147 return isolate->Throw(*error); 1148 return isolate->Throw(*error);
1148 } 1149 }
1149 1150
1150 1151
1151 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { 1152 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1152 ASSERT(args.length() == 4); 1153 ASSERT(args.length() == 3);
1153 HandleScope scope(isolate); 1154 HandleScope scope(isolate);
1154 Handle<GlobalObject> global = Handle<GlobalObject>( 1155 Handle<GlobalObject> global = Handle<GlobalObject>(
1155 isolate->context()->global()); 1156 isolate->context()->global());
1156 1157
1157 Handle<Context> context = args.at<Context>(0); 1158 Handle<Context> context = args.at<Context>(0);
1158 CONVERT_ARG_CHECKED(FixedArray, pairs, 1); 1159 CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
1159 bool is_eval = args.smi_at(2) == 1; 1160 CONVERT_SMI_ARG_CHECKED(flags, 2);
1160 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
1161 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
1162
1163 // Compute the property attributes. According to ECMA-262, section
1164 // 13, page 71, the property must be read-only and
1165 // non-deletable. However, neither SpiderMonkey nor KJS creates the
1166 // property as read-only, so we don't either.
1167 PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
1168 1161
1169 // Traverse the name/value pairs and set the properties. 1162 // Traverse the name/value pairs and set the properties.
1170 int length = pairs->length(); 1163 int length = pairs->length();
1171 for (int i = 0; i < length; i += 2) { 1164 for (int i = 0; i < length; i += 2) {
1172 HandleScope scope(isolate); 1165 HandleScope scope(isolate);
1173 Handle<String> name(String::cast(pairs->get(i))); 1166 Handle<String> name(String::cast(pairs->get(i)));
1174 Handle<Object> value(pairs->get(i + 1), isolate); 1167 Handle<Object> value(pairs->get(i + 1), isolate);
1175 1168
1176 // We have to declare a global const property. To capture we only 1169 // We have to declare a global const property. To capture we only
1177 // assign to it when evaluating the assignment for "const x = 1170 // assign to it when evaluating the assignment for "const x =
1178 // <expr>" the initial value is the hole. 1171 // <expr>" the initial value is the hole.
1179 bool is_const_property = value->IsTheHole(); 1172 bool is_const_property = value->IsTheHole();
1180 1173 bool is_function_declaration = false;
1181 if (value->IsUndefined() || is_const_property) { 1174 if (value->IsUndefined() || is_const_property) {
1182 // Lookup the property in the global object, and don't set the 1175 // Lookup the property in the global object, and don't set the
1183 // value of the variable if the property is already there. 1176 // value of the variable if the property is already there.
1184 LookupResult lookup; 1177 LookupResult lookup;
1185 global->Lookup(*name, &lookup); 1178 global->Lookup(*name, &lookup);
1186 if (lookup.IsProperty()) { 1179 if (lookup.IsProperty()) {
1187 // Determine if the property is local by comparing the holder 1180 // Determine if the property is local by comparing the holder
1188 // against the global object. The information will be used to 1181 // against the global object. The information will be used to
1189 // avoid throwing re-declaration errors when declaring 1182 // avoid throwing re-declaration errors when declaring
1190 // variables or constants that exist in the prototype chain. 1183 // variables or constants that exist in the prototype chain.
(...skipping 28 matching lines...) Expand all
1219 if (is_local && (is_read_only || is_const_property)) { 1212 if (is_local && (is_read_only || is_const_property)) {
1220 const char* type = (is_read_only) ? "const" : "var"; 1213 const char* type = (is_read_only) ? "const" : "var";
1221 return ThrowRedeclarationError(isolate, type, name); 1214 return ThrowRedeclarationError(isolate, type, name);
1222 } 1215 }
1223 // The property already exists without conflicting: Go to 1216 // The property already exists without conflicting: Go to
1224 // the next declaration. 1217 // the next declaration.
1225 continue; 1218 continue;
1226 } 1219 }
1227 } 1220 }
1228 } else { 1221 } else {
1222 is_function_declaration = true;
1229 // Copy the function and update its context. Use it as value. 1223 // Copy the function and update its context. Use it as value.
1230 Handle<SharedFunctionInfo> shared = 1224 Handle<SharedFunctionInfo> shared =
1231 Handle<SharedFunctionInfo>::cast(value); 1225 Handle<SharedFunctionInfo>::cast(value);
1232 Handle<JSFunction> function = 1226 Handle<JSFunction> function =
1233 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, 1227 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
1234 context, 1228 context,
1235 TENURED); 1229 TENURED);
1236 value = function; 1230 value = function;
1237 } 1231 }
1238 1232
1239 LookupResult lookup; 1233 LookupResult lookup;
1240 global->LocalLookup(*name, &lookup); 1234 global->LocalLookup(*name, &lookup);
1241 1235
1242 PropertyAttributes attributes = is_const_property
1243 ? static_cast<PropertyAttributes>(base | READ_ONLY)
1244 : base;
1245
1246 // There's a local property that we need to overwrite because 1236 // There's a local property that we need to overwrite because
1247 // we're either declaring a function or there's an interceptor 1237 // we're either declaring a function or there's an interceptor
1248 // that claims the property is absent. 1238 // that claims the property is absent.
1249 // 1239 //
1250 // Check for conflicting re-declarations. We cannot have 1240 // Check for conflicting re-declarations. We cannot have
1251 // conflicting types in case of intercepted properties because 1241 // conflicting types in case of intercepted properties because
1252 // they are absent. 1242 // they are absent.
1253 if (lookup.IsProperty() && 1243 if (lookup.IsProperty() &&
1254 (lookup.type() != INTERCEPTOR) && 1244 (lookup.type() != INTERCEPTOR) &&
1255 (lookup.IsReadOnly() || is_const_property)) { 1245 (lookup.IsReadOnly() || is_const_property)) {
1256 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; 1246 const char* type = (lookup.IsReadOnly()) ? "const" : "var";
1257 return ThrowRedeclarationError(isolate, type, name); 1247 return ThrowRedeclarationError(isolate, type, name);
1258 } 1248 }
1259 1249
1250 // Compute the property attributes. According to ECMA-262, section
1251 // 13, page 71, the property must be read-only and
1252 // non-deletable. However, neither SpiderMonkey nor KJS creates the
1253 // property as read-only, so we don't either.
1254 int attr = NONE;
1255 if ((flags & kDeclareGlobalsEvalFlag) == 0) {
1256 attr |= DONT_DELETE;
1257 }
1258 bool is_native = (flags & kDeclareGlobalsNativeFlag) != 0;
1259 if (is_const_property || (is_native && is_function_declaration)) {
1260 attr |= READ_ONLY;
1261 }
1262
1260 // Safari does not allow the invocation of callback setters for 1263 // Safari does not allow the invocation of callback setters for
1261 // function declarations. To mimic this behavior, we do not allow 1264 // function declarations. To mimic this behavior, we do not allow
1262 // the invocation of setters for function values. This makes a 1265 // the invocation of setters for function values. This makes a
1263 // difference for global functions with the same names as event 1266 // difference for global functions with the same names as event
1264 // handlers such as "function onload() {}". Firefox does call the 1267 // handlers such as "function onload() {}". Firefox does call the
1265 // onload setter in those case and Safari does not. We follow 1268 // onload setter in those case and Safari does not. We follow
1266 // Safari for compatibility. 1269 // Safari for compatibility.
1267 if (value->IsJSFunction()) { 1270 if (value->IsJSFunction()) {
1268 // Do not change DONT_DELETE to false from true. 1271 // Do not change DONT_DELETE to false from true.
1269 if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) { 1272 if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) {
1270 attributes = static_cast<PropertyAttributes>( 1273 attr |= lookup.GetAttributes() & DONT_DELETE;
1271 attributes | (lookup.GetAttributes() & DONT_DELETE));
1272 } 1274 }
1275 PropertyAttributes attributes = static_cast<PropertyAttributes>(attr);
1276
1273 RETURN_IF_EMPTY_HANDLE(isolate, 1277 RETURN_IF_EMPTY_HANDLE(isolate,
1274 SetLocalPropertyIgnoreAttributes(global, 1278 SetLocalPropertyIgnoreAttributes(global,
1275 name, 1279 name,
1276 value, 1280 value,
1277 attributes)); 1281 attributes));
1278 } else { 1282 } else {
1283 StrictModeFlag strict_mode =
1284 ((flags & kDeclareGlobalsStrictModeFlag) != 0) ? kStrictMode
1285 : kNonStrictMode;
1279 RETURN_IF_EMPTY_HANDLE(isolate, 1286 RETURN_IF_EMPTY_HANDLE(isolate,
1280 SetProperty(global, 1287 SetProperty(global,
1281 name, 1288 name,
1282 value, 1289 value,
1283 attributes, 1290 static_cast<PropertyAttributes>(attr),
1284 strict_mode)); 1291 strict_mode));
1285 } 1292 }
1286 } 1293 }
1287 1294
1288 ASSERT(!isolate->has_pending_exception()); 1295 ASSERT(!isolate->has_pending_exception());
1289 return isolate->heap()->undefined_value(); 1296 return isolate->heap()->undefined_value();
1290 } 1297 }
1291 1298
1292 1299
1293 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { 1300 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
1294 HandleScope scope(isolate); 1301 HandleScope scope(isolate);
1295 ASSERT(args.length() == 4); 1302 ASSERT(args.length() == 4);
1296 1303
1297 CONVERT_ARG_CHECKED(Context, context, 0); 1304 CONVERT_ARG_CHECKED(Context, context, 0);
1298 Handle<String> name(String::cast(args[1])); 1305 Handle<String> name(String::cast(args[1]));
1299 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2)); 1306 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
1300 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); 1307 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
1301 Handle<Object> initial_value(args[3], isolate); 1308 Handle<Object> initial_value(args[3], isolate);
1302 1309
1303 // Declarations are always done in a function or global context. 1310 // Declarations are always done in a function or global context.
1304 context = Handle<Context>(context->declaration_context()); 1311 context = Handle<Context>(context->declaration_context());
1305 1312
1306 int index; 1313 int index;
1307 PropertyAttributes attributes; 1314 PropertyAttributes attributes;
1308 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; 1315 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
1316 BindingFlags binding_flags;
1309 Handle<Object> holder = 1317 Handle<Object> holder =
1310 context->Lookup(name, flags, &index, &attributes); 1318 context->Lookup(name, flags, &index, &attributes, &binding_flags);
1311 1319
1312 if (attributes != ABSENT) { 1320 if (attributes != ABSENT) {
1313 // The name was declared before; check for conflicting 1321 // The name was declared before; check for conflicting
1314 // re-declarations: This is similar to the code in parser.cc in 1322 // re-declarations: This is similar to the code in parser.cc in
1315 // the AstBuildingParser::Declare function. 1323 // the AstBuildingParser::Declare function.
1316 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) { 1324 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
1317 // Functions are not read-only. 1325 // Functions are not read-only.
1318 ASSERT(mode != READ_ONLY || initial_value->IsTheHole()); 1326 ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
1319 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var"; 1327 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
1320 return ThrowRedeclarationError(isolate, type, name); 1328 return ThrowRedeclarationError(isolate, type, name);
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
1587 ASSERT(!value->IsTheHole()); 1595 ASSERT(!value->IsTheHole());
1588 CONVERT_ARG_CHECKED(Context, context, 1); 1596 CONVERT_ARG_CHECKED(Context, context, 1);
1589 Handle<String> name(String::cast(args[2])); 1597 Handle<String> name(String::cast(args[2]));
1590 1598
1591 // Initializations are always done in a function or global context. 1599 // Initializations are always done in a function or global context.
1592 context = Handle<Context>(context->declaration_context()); 1600 context = Handle<Context>(context->declaration_context());
1593 1601
1594 int index; 1602 int index;
1595 PropertyAttributes attributes; 1603 PropertyAttributes attributes;
1596 ContextLookupFlags flags = FOLLOW_CHAINS; 1604 ContextLookupFlags flags = FOLLOW_CHAINS;
1605 BindingFlags binding_flags;
1597 Handle<Object> holder = 1606 Handle<Object> holder =
1598 context->Lookup(name, flags, &index, &attributes); 1607 context->Lookup(name, flags, &index, &attributes, &binding_flags);
1599 1608
1600 // In most situations, the property introduced by the const 1609 // In most situations, the property introduced by the const
1601 // declaration should be present in the context extension object. 1610 // declaration should be present in the context extension object.
1602 // However, because declaration and initialization are separate, the 1611 // However, because declaration and initialization are separate, the
1603 // property might have been deleted (if it was introduced by eval) 1612 // property might have been deleted (if it was introduced by eval)
1604 // before we reach the initialization point. 1613 // before we reach the initialization point.
1605 // 1614 //
1606 // Example: 1615 // Example:
1607 // 1616 //
1608 // function f() { eval("delete x; const x;"); } 1617 // function f() { eval("delete x; const x;"); }
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1859 InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift); 1868 InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
1860 InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift); 1869 InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
1861 InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice); 1870 InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
1862 InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice); 1871 InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
1863 InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat); 1872 InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
1864 1873
1865 return *holder; 1874 return *holder;
1866 } 1875 }
1867 1876
1868 1877
1869 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetGlobalReceiver) { 1878 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
1870 // Returns a real global receiver, not one of builtins object. 1879 NoHandleAllocation handle_free;
1880 ASSERT(args.length() == 1);
1881 CONVERT_CHECKED(JSFunction, function, args[0]);
1882 SharedFunctionInfo* shared = function->shared();
1883 if (shared->native() || shared->strict_mode()) {
1884 return isolate->heap()->undefined_value();
1885 }
1886 // Returns undefined for strict or native functions, or
1887 // the associated global receiver for "normal" functions.
1888
1871 Context* global_context = 1889 Context* global_context =
1872 isolate->context()->global()->global_context(); 1890 function->context()->global()->global_context();
1873 return global_context->global()->global_receiver(); 1891 return global_context->global()->global_receiver();
1874 } 1892 }
1875 1893
1876 1894
1877 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) { 1895 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
1878 HandleScope scope(isolate); 1896 HandleScope scope(isolate);
1879 ASSERT(args.length() == 4); 1897 ASSERT(args.length() == 4);
1880 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 1898 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
1881 int index = args.smi_at(1); 1899 int index = args.smi_at(1);
1882 Handle<String> pattern = args.at<String>(2); 1900 Handle<String> pattern = args.at<String>(2);
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
2129 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) { 2147 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2130 NoHandleAllocation ha; 2148 NoHandleAllocation ha;
2131 ASSERT(args.length() == 1); 2149 ASSERT(args.length() == 1);
2132 2150
2133 CONVERT_CHECKED(JSFunction, f, args[0]); 2151 CONVERT_CHECKED(JSFunction, f, args[0]);
2134 return isolate->heap()->ToBoolean(f->IsBuiltin()); 2152 return isolate->heap()->ToBoolean(f->IsBuiltin());
2135 } 2153 }
2136 2154
2137 2155
2138 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) { 2156 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2157 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
2139 HandleScope scope(isolate); 2158 HandleScope scope(isolate);
2140 ASSERT(args.length() == 2); 2159 ASSERT(args.length() == 2);
2141 2160
2142 CONVERT_ARG_CHECKED(JSFunction, target, 0); 2161 CONVERT_ARG_CHECKED(JSFunction, target, 0);
2143 Handle<Object> code = args.at<Object>(1); 2162 Handle<Object> code = args.at<Object>(1);
2144 2163
2145 Handle<Context> context(target->context()); 2164 Handle<Context> context(target->context());
2146 2165
2147 if (!code->IsNull()) { 2166 if (!code->IsNull()) {
2148 RUNTIME_ASSERT(code->IsJSFunction()); 2167 RUNTIME_ASSERT(code->IsJSFunction());
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
2479 FixedArrayBuilder array_builder_; 2498 FixedArrayBuilder array_builder_;
2480 Handle<String> subject_; 2499 Handle<String> subject_;
2481 int character_count_; 2500 int character_count_;
2482 bool is_ascii_; 2501 bool is_ascii_;
2483 }; 2502 };
2484 2503
2485 2504
2486 class CompiledReplacement { 2505 class CompiledReplacement {
2487 public: 2506 public:
2488 CompiledReplacement() 2507 CompiledReplacement()
2489 : parts_(1), replacement_substrings_(0) {} 2508 : parts_(1), replacement_substrings_(0), simple_hint_(false) {}
2490 2509
2491 void Compile(Handle<String> replacement, 2510 void Compile(Handle<String> replacement,
2492 int capture_count, 2511 int capture_count,
2493 int subject_length); 2512 int subject_length);
2494 2513
2495 void Apply(ReplacementStringBuilder* builder, 2514 void Apply(ReplacementStringBuilder* builder,
2496 int match_from, 2515 int match_from,
2497 int match_to, 2516 int match_to,
2498 Handle<JSArray> last_match_info); 2517 Handle<JSArray> last_match_info);
2499 2518
2500 // Number of distinct parts of the replacement pattern. 2519 // Number of distinct parts of the replacement pattern.
2501 int parts() { 2520 int parts() {
2502 return parts_.length(); 2521 return parts_.length();
2503 } 2522 }
2504 2523
2524 bool simple_hint() {
2525 return simple_hint_;
2526 }
2527
2505 private: 2528 private:
2506 enum PartType { 2529 enum PartType {
2507 SUBJECT_PREFIX = 1, 2530 SUBJECT_PREFIX = 1,
2508 SUBJECT_SUFFIX, 2531 SUBJECT_SUFFIX,
2509 SUBJECT_CAPTURE, 2532 SUBJECT_CAPTURE,
2510 REPLACEMENT_SUBSTRING, 2533 REPLACEMENT_SUBSTRING,
2511 REPLACEMENT_STRING, 2534 REPLACEMENT_STRING,
2512 2535
2513 NUMBER_OF_PART_TYPES 2536 NUMBER_OF_PART_TYPES
2514 }; 2537 };
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2553 // tag == REPLACEMENT_STRING: data is index into array of substrings 2576 // tag == REPLACEMENT_STRING: data is index into array of substrings
2554 // of the replacement string. 2577 // of the replacement string.
2555 // tag <= 0: Temporary representation of the substring of the replacement 2578 // tag <= 0: Temporary representation of the substring of the replacement
2556 // string ranging over -tag .. data. 2579 // string ranging over -tag .. data.
2557 // Is replaced by REPLACEMENT_{SUB,}STRING when we create the 2580 // Is replaced by REPLACEMENT_{SUB,}STRING when we create the
2558 // substring objects. 2581 // substring objects.
2559 int data; 2582 int data;
2560 }; 2583 };
2561 2584
2562 template<typename Char> 2585 template<typename Char>
2563 static void ParseReplacementPattern(ZoneList<ReplacementPart>* parts, 2586 static bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
2564 Vector<Char> characters, 2587 Vector<Char> characters,
2565 int capture_count, 2588 int capture_count,
2566 int subject_length) { 2589 int subject_length) {
2567 int length = characters.length(); 2590 int length = characters.length();
2568 int last = 0; 2591 int last = 0;
2569 for (int i = 0; i < length; i++) { 2592 for (int i = 0; i < length; i++) {
2570 Char c = characters[i]; 2593 Char c = characters[i];
2571 if (c == '$') { 2594 if (c == '$') {
2572 int next_index = i + 1; 2595 int next_index = i + 1;
2573 if (next_index == length) { // No next character! 2596 if (next_index == length) { // No next character!
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2650 } 2673 }
2651 default: 2674 default:
2652 i = next_index; 2675 i = next_index;
2653 break; 2676 break;
2654 } 2677 }
2655 } 2678 }
2656 } 2679 }
2657 if (length > last) { 2680 if (length > last) {
2658 if (last == 0) { 2681 if (last == 0) {
2659 parts->Add(ReplacementPart::ReplacementString()); 2682 parts->Add(ReplacementPart::ReplacementString());
2683 return true;
2660 } else { 2684 } else {
2661 parts->Add(ReplacementPart::ReplacementSubString(last, length)); 2685 parts->Add(ReplacementPart::ReplacementSubString(last, length));
2662 } 2686 }
2663 } 2687 }
2688 return false;
2664 } 2689 }
2665 2690
2666 ZoneList<ReplacementPart> parts_; 2691 ZoneList<ReplacementPart> parts_;
2667 ZoneList<Handle<String> > replacement_substrings_; 2692 ZoneList<Handle<String> > replacement_substrings_;
2693 bool simple_hint_;
2668 }; 2694 };
2669 2695
2670 2696
2671 void CompiledReplacement::Compile(Handle<String> replacement, 2697 void CompiledReplacement::Compile(Handle<String> replacement,
2672 int capture_count, 2698 int capture_count,
2673 int subject_length) { 2699 int subject_length) {
2674 { 2700 {
2675 AssertNoAllocation no_alloc; 2701 AssertNoAllocation no_alloc;
2676 String::FlatContent content = replacement->GetFlatContent(); 2702 String::FlatContent content = replacement->GetFlatContent();
2677 ASSERT(content.IsFlat()); 2703 ASSERT(content.IsFlat());
2678 if (content.IsAscii()) { 2704 if (content.IsAscii()) {
2679 ParseReplacementPattern(&parts_, 2705 simple_hint_ = ParseReplacementPattern(&parts_,
2680 content.ToAsciiVector(), 2706 content.ToAsciiVector(),
2681 capture_count, 2707 capture_count,
2682 subject_length); 2708 subject_length);
2683 } else { 2709 } else {
2684 ASSERT(content.IsTwoByte()); 2710 ASSERT(content.IsTwoByte());
2685 ParseReplacementPattern(&parts_, 2711 simple_hint_ = ParseReplacementPattern(&parts_,
2686 content.ToUC16Vector(), 2712 content.ToUC16Vector(),
2687 capture_count, 2713 capture_count,
2688 subject_length); 2714 subject_length);
2689 } 2715 }
2690 } 2716 }
2691 Isolate* isolate = replacement->GetIsolate(); 2717 Isolate* isolate = replacement->GetIsolate();
2692 // Find substrings of replacement string and create them as String objects. 2718 // Find substrings of replacement string and create them as String objects.
2693 int substring_index = 0; 2719 int substring_index = 0;
2694 for (int i = 0, n = parts_.length(); i < n; i++) { 2720 for (int i = 0, n = parts_.length(); i < n; i++) {
2695 int tag = parts_[i].tag; 2721 int tag = parts_[i].tag;
2696 if (tag <= 0) { // A replacement string slice. 2722 if (tag <= 0) { // A replacement string slice.
2697 int from = -tag; 2723 int from = -tag;
2698 int to = parts_[i].data; 2724 int to = parts_[i].data;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2741 case REPLACEMENT_STRING: 2767 case REPLACEMENT_STRING:
2742 builder->AddString(replacement_substrings_[part.data]); 2768 builder->AddString(replacement_substrings_[part.data]);
2743 break; 2769 break;
2744 default: 2770 default:
2745 UNREACHABLE(); 2771 UNREACHABLE();
2746 } 2772 }
2747 } 2773 }
2748 } 2774 }
2749 2775
2750 2776
2777 void FindAsciiStringIndices(Vector<const char> subject,
2778 char pattern,
2779 ZoneList<int>* indices,
2780 unsigned int limit) {
2781 ASSERT(limit > 0);
2782 // Collect indices of pattern in subject using memchr.
2783 // Stop after finding at most limit values.
2784 const char* subject_start = reinterpret_cast<const char*>(subject.start());
2785 const char* subject_end = subject_start + subject.length();
2786 const char* pos = subject_start;
2787 while (limit > 0) {
2788 pos = reinterpret_cast<const char*>(
2789 memchr(pos, pattern, subject_end - pos));
2790 if (pos == NULL) return;
2791 indices->Add(static_cast<int>(pos - subject_start));
2792 pos++;
2793 limit--;
2794 }
2795 }
2796
2797
2798 template <typename SubjectChar, typename PatternChar>
2799 void FindStringIndices(Isolate* isolate,
2800 Vector<const SubjectChar> subject,
2801 Vector<const PatternChar> pattern,
2802 ZoneList<int>* indices,
2803 unsigned int limit) {
2804 ASSERT(limit > 0);
2805 // Collect indices of pattern in subject.
2806 // Stop after finding at most limit values.
2807 int pattern_length = pattern.length();
2808 int index = 0;
2809 StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
2810 while (limit > 0) {
2811 index = search.Search(subject, index);
2812 if (index < 0) return;
2813 indices->Add(index);
2814 index += pattern_length;
2815 limit--;
2816 }
2817 }
2818
2819
2820 void FindStringIndicesDispatch(Isolate* isolate,
2821 String* subject,
2822 String* pattern,
2823 ZoneList<int>* indices,
2824 unsigned int limit) {
2825 {
2826 AssertNoAllocation no_gc;
2827 String::FlatContent subject_content = subject->GetFlatContent();
2828 String::FlatContent pattern_content = pattern->GetFlatContent();
2829 ASSERT(subject_content.IsFlat());
2830 ASSERT(pattern_content.IsFlat());
2831 if (subject_content.IsAscii()) {
2832 Vector<const char> subject_vector = subject_content.ToAsciiVector();
2833 if (pattern_content.IsAscii()) {
2834 Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
2835 if (pattern_vector.length() == 1) {
2836 FindAsciiStringIndices(subject_vector,
2837 pattern_vector[0],
2838 indices,
2839 limit);
2840 } else {
2841 FindStringIndices(isolate,
2842 subject_vector,
2843 pattern_vector,
2844 indices,
2845 limit);
2846 }
2847 } else {
2848 FindStringIndices(isolate,
2849 subject_vector,
2850 pattern_content.ToUC16Vector(),
2851 indices,
2852 limit);
2853 }
2854 } else {
2855 Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
2856 if (pattern->IsAsciiRepresentation()) {
2857 FindStringIndices(isolate,
2858 subject_vector,
2859 pattern_content.ToAsciiVector(),
2860 indices,
2861 limit);
2862 } else {
2863 FindStringIndices(isolate,
2864 subject_vector,
2865 pattern_content.ToUC16Vector(),
2866 indices,
2867 limit);
2868 }
2869 }
2870 }
2871 }
2872
2873
2874 template<typename ResultSeqString>
2875 MUST_USE_RESULT static MaybeObject* StringReplaceStringWithString(
2876 Isolate* isolate,
2877 Handle<String> subject,
2878 Handle<JSRegExp> pattern_regexp,
2879 Handle<String> replacement) {
2880 ASSERT(subject->IsFlat());
2881 ASSERT(replacement->IsFlat());
2882
2883 ZoneScope zone_space(isolate, DELETE_ON_EXIT);
2884 ZoneList<int> indices(8);
2885 ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
2886 String* pattern =
2887 String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
2888 int subject_len = subject->length();
2889 int pattern_len = pattern->length();
2890 int replacement_len = replacement->length();
2891
2892 FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff);
2893
2894 int matches = indices.length();
2895 if (matches == 0) return *subject;
2896
2897 int result_len = (replacement_len - pattern_len) * matches + subject_len;
2898 int subject_pos = 0;
2899 int result_pos = 0;
2900
2901 Handle<ResultSeqString> result;
2902 if (ResultSeqString::kHasAsciiEncoding) {
2903 result = Handle<ResultSeqString>::cast(
2904 isolate->factory()->NewRawAsciiString(result_len));
2905 } else {
2906 result = Handle<ResultSeqString>::cast(
2907 isolate->factory()->NewRawTwoByteString(result_len));
2908 }
2909
2910 for (int i = 0; i < matches; i++) {
2911 // Copy non-matched subject content.
2912 if (subject_pos < indices.at(i)) {
2913 String::WriteToFlat(*subject,
2914 result->GetChars() + result_pos,
2915 subject_pos,
2916 indices.at(i));
2917 result_pos += indices.at(i) - subject_pos;
2918 }
2919
2920 // Replace match.
2921 if (replacement_len > 0) {
2922 String::WriteToFlat(*replacement,
2923 result->GetChars() + result_pos,
2924 0,
2925 replacement_len);
2926 result_pos += replacement_len;
2927 }
2928
2929 subject_pos = indices.at(i) + pattern_len;
2930 }
2931 // Add remaining subject content at the end.
2932 if (subject_pos < subject_len) {
2933 String::WriteToFlat(*subject,
2934 result->GetChars() + result_pos,
2935 subject_pos,
2936 subject_len);
2937 }
2938 return *result;
2939 }
2940
2751 2941
2752 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString( 2942 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
2753 Isolate* isolate, 2943 Isolate* isolate,
2754 String* subject, 2944 String* subject,
2755 JSRegExp* regexp, 2945 JSRegExp* regexp,
2756 String* replacement, 2946 String* replacement,
2757 JSArray* last_match_info) { 2947 JSArray* last_match_info) {
2758 ASSERT(subject->IsFlat()); 2948 ASSERT(subject->IsFlat());
2759 ASSERT(replacement->IsFlat()); 2949 ASSERT(replacement->IsFlat());
2760 2950
(...skipping 19 matching lines...) Expand all
2780 2970
2781 // CompiledReplacement uses zone allocation. 2971 // CompiledReplacement uses zone allocation.
2782 ZoneScope zone(isolate, DELETE_ON_EXIT); 2972 ZoneScope zone(isolate, DELETE_ON_EXIT);
2783 CompiledReplacement compiled_replacement; 2973 CompiledReplacement compiled_replacement;
2784 compiled_replacement.Compile(replacement_handle, 2974 compiled_replacement.Compile(replacement_handle,
2785 capture_count, 2975 capture_count,
2786 length); 2976 length);
2787 2977
2788 bool is_global = regexp_handle->GetFlags().is_global(); 2978 bool is_global = regexp_handle->GetFlags().is_global();
2789 2979
2980 // Shortcut for simple non-regexp global replacements
2981 if (is_global &&
2982 regexp->TypeTag() == JSRegExp::ATOM &&
2983 compiled_replacement.simple_hint()) {
2984 if (subject_handle->HasOnlyAsciiChars() &&
2985 replacement_handle->HasOnlyAsciiChars()) {
2986 return StringReplaceStringWithString<SeqAsciiString>(
2987 isolate, subject_handle, regexp_handle, replacement_handle);
2988 } else {
2989 return StringReplaceStringWithString<SeqTwoByteString>(
2990 isolate, subject_handle, regexp_handle, replacement_handle);
2991 }
2992 }
2993
2790 // Guessing the number of parts that the final result string is built 2994 // Guessing the number of parts that the final result string is built
2791 // from. Global regexps can match any number of times, so we guess 2995 // from. Global regexps can match any number of times, so we guess
2792 // conservatively. 2996 // conservatively.
2793 int expected_parts = 2997 int expected_parts =
2794 (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1; 2998 (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
2795 ReplacementStringBuilder builder(isolate->heap(), 2999 ReplacementStringBuilder builder(isolate->heap(),
2796 subject_handle, 3000 subject_handle,
2797 expected_parts); 3001 expected_parts);
2798 3002
2799 // Index of end of last match. 3003 // Index of end of last match.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2865 Isolate* isolate, 3069 Isolate* isolate,
2866 String* subject, 3070 String* subject,
2867 JSRegExp* regexp, 3071 JSRegExp* regexp,
2868 JSArray* last_match_info) { 3072 JSArray* last_match_info) {
2869 ASSERT(subject->IsFlat()); 3073 ASSERT(subject->IsFlat());
2870 3074
2871 HandleScope handles(isolate); 3075 HandleScope handles(isolate);
2872 3076
2873 Handle<String> subject_handle(subject); 3077 Handle<String> subject_handle(subject);
2874 Handle<JSRegExp> regexp_handle(regexp); 3078 Handle<JSRegExp> regexp_handle(regexp);
3079
3080 // Shortcut for simple non-regexp global replacements
3081 if (regexp_handle->GetFlags().is_global() &&
3082 regexp_handle->TypeTag() == JSRegExp::ATOM) {
3083 Handle<String> empty_string_handle(HEAP->empty_string());
3084 if (subject_handle->HasOnlyAsciiChars()) {
3085 return StringReplaceStringWithString<SeqAsciiString>(
3086 isolate, subject_handle, regexp_handle, empty_string_handle);
3087 } else {
3088 return StringReplaceStringWithString<SeqTwoByteString>(
3089 isolate, subject_handle, regexp_handle, empty_string_handle);
3090 }
3091 }
3092
2875 Handle<JSArray> last_match_info_handle(last_match_info); 3093 Handle<JSArray> last_match_info_handle(last_match_info);
2876 Handle<Object> match = RegExpImpl::Exec(regexp_handle, 3094 Handle<Object> match = RegExpImpl::Exec(regexp_handle,
2877 subject_handle, 3095 subject_handle,
2878 0, 3096 0,
2879 last_match_info_handle); 3097 last_match_info_handle);
2880 if (match.is_null()) return Failure::Exception(); 3098 if (match.is_null()) return Failure::Exception();
2881 if (match->IsNull()) return *subject_handle; 3099 if (match->IsNull()) return *subject_handle;
2882 3100
2883 ASSERT(last_match_info_handle->HasFastElements()); 3101 ASSERT(last_match_info_handle->HasFastElements());
2884 3102
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
3668 // No matches at all, return failure or exception result directly. 3886 // No matches at all, return failure or exception result directly.
3669 return result; 3887 return result;
3670 } 3888 }
3671 3889
3672 3890
3673 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) { 3891 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
3674 ASSERT(args.length() == 4); 3892 ASSERT(args.length() == 4);
3675 HandleScope handles(isolate); 3893 HandleScope handles(isolate);
3676 3894
3677 CONVERT_ARG_CHECKED(String, subject, 1); 3895 CONVERT_ARG_CHECKED(String, subject, 1);
3678 if (!subject->IsFlat()) { FlattenString(subject); } 3896 if (!subject->IsFlat()) FlattenString(subject);
3679 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); 3897 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
3680 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2); 3898 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
3681 CONVERT_ARG_CHECKED(JSArray, result_array, 3); 3899 CONVERT_ARG_CHECKED(JSArray, result_array, 3);
3682 3900
3683 ASSERT(last_match_info->HasFastElements()); 3901 ASSERT(last_match_info->HasFastElements());
3684 ASSERT(regexp->GetFlags().is_global()); 3902 ASSERT(regexp->GetFlags().is_global());
3685 Handle<FixedArray> result_elements; 3903 Handle<FixedArray> result_elements;
3686 if (result_array->HasFastElements()) { 3904 if (result_array->HasFastElements()) {
3687 result_elements = 3905 result_elements =
3688 Handle<FixedArray>(FixedArray::cast(result_array->elements())); 3906 Handle<FixedArray>(FixedArray::cast(result_array->elements()));
(...skipping 2216 matching lines...) Expand 10 before | Expand all | Expand 10 after
5905 int right = length; 6123 int right = length;
5906 if (trimRight) { 6124 if (trimRight) {
5907 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) { 6125 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
5908 right--; 6126 right--;
5909 } 6127 }
5910 } 6128 }
5911 return s->SubString(left, right); 6129 return s->SubString(left, right);
5912 } 6130 }
5913 6131
5914 6132
5915 void FindAsciiStringIndices(Vector<const char> subject,
5916 char pattern,
5917 ZoneList<int>* indices,
5918 unsigned int limit) {
5919 ASSERT(limit > 0);
5920 // Collect indices of pattern in subject using memchr.
5921 // Stop after finding at most limit values.
5922 const char* subject_start = reinterpret_cast<const char*>(subject.start());
5923 const char* subject_end = subject_start + subject.length();
5924 const char* pos = subject_start;
5925 while (limit > 0) {
5926 pos = reinterpret_cast<const char*>(
5927 memchr(pos, pattern, subject_end - pos));
5928 if (pos == NULL) return;
5929 indices->Add(static_cast<int>(pos - subject_start));
5930 pos++;
5931 limit--;
5932 }
5933 }
5934
5935
5936 template <typename SubjectChar, typename PatternChar>
5937 void FindStringIndices(Isolate* isolate,
5938 Vector<const SubjectChar> subject,
5939 Vector<const PatternChar> pattern,
5940 ZoneList<int>* indices,
5941 unsigned int limit) {
5942 ASSERT(limit > 0);
5943 // Collect indices of pattern in subject.
5944 // Stop after finding at most limit values.
5945 int pattern_length = pattern.length();
5946 int index = 0;
5947 StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
5948 while (limit > 0) {
5949 index = search.Search(subject, index);
5950 if (index < 0) return;
5951 indices->Add(index);
5952 index += pattern_length;
5953 limit--;
5954 }
5955 }
5956
5957
5958 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) { 6133 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
5959 ASSERT(args.length() == 3); 6134 ASSERT(args.length() == 3);
5960 HandleScope handle_scope(isolate); 6135 HandleScope handle_scope(isolate);
5961 CONVERT_ARG_CHECKED(String, subject, 0); 6136 CONVERT_ARG_CHECKED(String, subject, 0);
5962 CONVERT_ARG_CHECKED(String, pattern, 1); 6137 CONVERT_ARG_CHECKED(String, pattern, 1);
5963 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]); 6138 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
5964 6139
5965 int subject_length = subject->length(); 6140 int subject_length = subject->length();
5966 int pattern_length = pattern->length(); 6141 int pattern_length = pattern->length();
5967 RUNTIME_ASSERT(pattern_length > 0); 6142 RUNTIME_ASSERT(pattern_length > 0);
5968 6143
6144 if (limit == 0xffffffffu) {
6145 Handle<Object> cached_answer(StringSplitCache::Lookup(
6146 isolate->heap()->string_split_cache(),
6147 *subject,
6148 *pattern));
6149 if (*cached_answer != Smi::FromInt(0)) {
6150 Handle<JSArray> result =
6151 isolate->factory()->NewJSArrayWithElements(
6152 Handle<FixedArray>::cast(cached_answer));
6153 return *result;
6154 }
6155 }
6156
5969 // The limit can be very large (0xffffffffu), but since the pattern 6157 // The limit can be very large (0xffffffffu), but since the pattern
5970 // isn't empty, we can never create more parts than ~half the length 6158 // isn't empty, we can never create more parts than ~half the length
5971 // of the subject. 6159 // of the subject.
5972 6160
5973 if (!subject->IsFlat()) FlattenString(subject); 6161 if (!subject->IsFlat()) FlattenString(subject);
5974 6162
5975 static const int kMaxInitialListCapacity = 16; 6163 static const int kMaxInitialListCapacity = 16;
5976 6164
5977 ZoneScope scope(isolate, DELETE_ON_EXIT); 6165 ZoneScope scope(isolate, DELETE_ON_EXIT);
5978 6166
5979 // Find (up to limit) indices of separator and end-of-string in subject 6167 // Find (up to limit) indices of separator and end-of-string in subject
5980 int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit); 6168 int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
5981 ZoneList<int> indices(initial_capacity); 6169 ZoneList<int> indices(initial_capacity);
5982 if (!pattern->IsFlat()) FlattenString(pattern); 6170 if (!pattern->IsFlat()) FlattenString(pattern);
5983 6171
5984 // No allocation block. 6172 FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit);
5985 {
5986 AssertNoAllocation no_gc;
5987 String::FlatContent subject_content = subject->GetFlatContent();
5988 String::FlatContent pattern_content = pattern->GetFlatContent();
5989 ASSERT(subject_content.IsFlat());
5990 ASSERT(pattern_content.IsFlat());
5991 if (subject_content.IsAscii()) {
5992 Vector<const char> subject_vector = subject_content.ToAsciiVector();
5993 if (pattern_content.IsAscii()) {
5994 Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
5995 if (pattern_vector.length() == 1) {
5996 FindAsciiStringIndices(subject_vector,
5997 pattern_vector[0],
5998 &indices,
5999 limit);
6000 } else {
6001 FindStringIndices(isolate,
6002 subject_vector,
6003 pattern_vector,
6004 &indices,
6005 limit);
6006 }
6007 } else {
6008 FindStringIndices(isolate,
6009 subject_vector,
6010 pattern_content.ToUC16Vector(),
6011 &indices,
6012 limit);
6013 }
6014 } else {
6015 Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
6016 if (pattern->IsAsciiRepresentation()) {
6017 FindStringIndices(isolate,
6018 subject_vector,
6019 pattern_content.ToAsciiVector(),
6020 &indices,
6021 limit);
6022 } else {
6023 FindStringIndices(isolate,
6024 subject_vector,
6025 pattern_content.ToUC16Vector(),
6026 &indices,
6027 limit);
6028 }
6029 }
6030 }
6031 6173
6032 if (static_cast<uint32_t>(indices.length()) < limit) { 6174 if (static_cast<uint32_t>(indices.length()) < limit) {
6033 indices.Add(subject_length); 6175 indices.Add(subject_length);
6034 } 6176 }
6035 6177
6036 // The list indices now contains the end of each part to create. 6178 // The list indices now contains the end of each part to create.
6037 6179
6038 // Create JSArray of substrings separated by separator. 6180 // Create JSArray of substrings separated by separator.
6039 int part_count = indices.length(); 6181 int part_count = indices.length();
6040 6182
(...skipping 11 matching lines...) Expand all
6052 int part_start = 0; 6194 int part_start = 0;
6053 for (int i = 0; i < part_count; i++) { 6195 for (int i = 0; i < part_count; i++) {
6054 HandleScope local_loop_handle; 6196 HandleScope local_loop_handle;
6055 int part_end = indices.at(i); 6197 int part_end = indices.at(i);
6056 Handle<String> substring = 6198 Handle<String> substring =
6057 isolate->factory()->NewProperSubString(subject, part_start, part_end); 6199 isolate->factory()->NewProperSubString(subject, part_start, part_end);
6058 elements->set(i, *substring); 6200 elements->set(i, *substring);
6059 part_start = part_end + pattern_length; 6201 part_start = part_end + pattern_length;
6060 } 6202 }
6061 6203
6204 if (limit == 0xffffffffu) {
6205 if (result->HasFastElements()) {
6206 StringSplitCache::Enter(isolate->heap(),
6207 isolate->heap()->string_split_cache(),
6208 *subject,
6209 *pattern,
6210 *elements);
6211 }
6212 }
6213
6062 return *result; 6214 return *result;
6063 } 6215 }
6064 6216
6065 6217
6066 // Copies ascii characters to the given fixed array looking up 6218 // Copies ascii characters to the given fixed array looking up
6067 // one-char strings in the cache. Gives up on the first char that is 6219 // one-char strings in the cache. Gives up on the first char that is
6068 // not in the cache and fills the remainder with smi zeros. Returns 6220 // not in the cache and fills the remainder with smi zeros. Returns
6069 // the length of the successfully copied prefix. 6221 // the length of the successfully copied prefix.
6070 static int CopyCachedAsciiCharsToArray(Heap* heap, 6222 static int CopyCachedAsciiCharsToArray(Heap* heap,
6071 const char* chars, 6223 const char* chars,
(...skipping 2161 matching lines...) Expand 10 before | Expand all | Expand 10 after
8233 return Smi::FromInt(ast_id); 8385 return Smi::FromInt(ast_id);
8234 } else { 8386 } else {
8235 if (function->IsMarkedForLazyRecompilation()) { 8387 if (function->IsMarkedForLazyRecompilation()) {
8236 function->ReplaceCode(function->shared()->code()); 8388 function->ReplaceCode(function->shared()->code());
8237 } 8389 }
8238 return Smi::FromInt(-1); 8390 return Smi::FromInt(-1);
8239 } 8391 }
8240 } 8392 }
8241 8393
8242 8394
8395 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8396 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8397 return isolate->heap()->undefined_value();
8398 }
8399
8400
8243 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) { 8401 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8244 HandleScope scope(isolate); 8402 HandleScope scope(isolate);
8245 ASSERT(args.length() == 1); 8403 ASSERT(args.length() == 1);
8246 RUNTIME_ASSERT(!args[0]->IsJSFunction()); 8404 RUNTIME_ASSERT(!args[0]->IsJSFunction());
8247 return *Execution::GetFunctionDelegate(args.at<Object>(0)); 8405 return *Execution::GetFunctionDelegate(args.at<Object>(0));
8248 } 8406 }
8249 8407
8250 8408
8251 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) { 8409 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8252 HandleScope scope(isolate); 8410 HandleScope scope(isolate);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
8371 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) { 8529 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
8372 HandleScope scope(isolate); 8530 HandleScope scope(isolate);
8373 ASSERT(args.length() == 2); 8531 ASSERT(args.length() == 2);
8374 8532
8375 CONVERT_ARG_CHECKED(Context, context, 0); 8533 CONVERT_ARG_CHECKED(Context, context, 0);
8376 CONVERT_ARG_CHECKED(String, name, 1); 8534 CONVERT_ARG_CHECKED(String, name, 1);
8377 8535
8378 int index; 8536 int index;
8379 PropertyAttributes attributes; 8537 PropertyAttributes attributes;
8380 ContextLookupFlags flags = FOLLOW_CHAINS; 8538 ContextLookupFlags flags = FOLLOW_CHAINS;
8381 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); 8539 BindingFlags binding_flags;
8540 Handle<Object> holder = context->Lookup(name,
8541 flags,
8542 &index,
8543 &attributes,
8544 &binding_flags);
8382 8545
8383 // If the slot was not found the result is true. 8546 // If the slot was not found the result is true.
8384 if (holder.is_null()) { 8547 if (holder.is_null()) {
8385 return isolate->heap()->true_value(); 8548 return isolate->heap()->true_value();
8386 } 8549 }
8387 8550
8388 // If the slot was found in a context, it should be DONT_DELETE. 8551 // If the slot was found in a context, it should be DONT_DELETE.
8389 if (holder->IsContext()) { 8552 if (holder->IsContext()) {
8390 return isolate->heap()->false_value(); 8553 return isolate->heap()->false_value();
8391 } 8554 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
8473 8636
8474 if (!args[0]->IsContext() || !args[1]->IsString()) { 8637 if (!args[0]->IsContext() || !args[1]->IsString()) {
8475 return MakePair(isolate->ThrowIllegalOperation(), NULL); 8638 return MakePair(isolate->ThrowIllegalOperation(), NULL);
8476 } 8639 }
8477 Handle<Context> context = args.at<Context>(0); 8640 Handle<Context> context = args.at<Context>(0);
8478 Handle<String> name = args.at<String>(1); 8641 Handle<String> name = args.at<String>(1);
8479 8642
8480 int index; 8643 int index;
8481 PropertyAttributes attributes; 8644 PropertyAttributes attributes;
8482 ContextLookupFlags flags = FOLLOW_CHAINS; 8645 ContextLookupFlags flags = FOLLOW_CHAINS;
8483 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); 8646 BindingFlags binding_flags;
8647 Handle<Object> holder = context->Lookup(name,
8648 flags,
8649 &index,
8650 &attributes,
8651 &binding_flags);
8484 8652
8485 // If the index is non-negative, the slot has been found in a local 8653 // If the index is non-negative, the slot has been found in a local
8486 // variable or a parameter. Read it from the context object or the 8654 // variable or a parameter. Read it from the context object or the
8487 // arguments object. 8655 // arguments object.
8488 if (index >= 0) { 8656 if (index >= 0) {
8489 // If the "property" we were looking for is a local variable or an 8657 // If the "property" we were looking for is a local variable or an
8490 // argument in a context, the receiver is the global object; see 8658 // argument in a context, the receiver is the global object; see
8491 // ECMA-262, 3rd., 10.1.6 and 10.2.3. 8659 // ECMA-262, 3rd., 10.1.6 and 10.2.3.
8492 // 8660 //
8493 // Use the hole as the receiver to signal that the receiver is 8661 // Use the hole as the receiver to signal that the receiver is
8494 // implicit and that the global receiver should be used. 8662 // implicit and that the global receiver should be used.
8495 Handle<Object> receiver = isolate->factory()->the_hole_value(); 8663 Handle<Object> receiver = isolate->factory()->the_hole_value();
8496 MaybeObject* value = (holder->IsContext()) 8664 MaybeObject* value = (holder->IsContext())
8497 ? Context::cast(*holder)->get(index) 8665 ? Context::cast(*holder)->get(index)
8498 : JSObject::cast(*holder)->GetElement(index); 8666 : JSObject::cast(*holder)->GetElement(index);
8499 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); 8667 // Check for uninitialized bindings.
8668 if (holder->IsContext() &&
8669 binding_flags == MUTABLE_CHECK_INITIALIZED &&
8670 value->IsTheHole()) {
8671 Handle<Object> reference_error =
8672 isolate->factory()->NewReferenceError("not_defined",
8673 HandleVector(&name, 1));
8674 return MakePair(isolate->Throw(*reference_error), NULL);
8675 } else {
8676 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
8677 }
8500 } 8678 }
8501 8679
8502 // If the holder is found, we read the property from it. 8680 // If the holder is found, we read the property from it.
8503 if (!holder.is_null() && holder->IsJSObject()) { 8681 if (!holder.is_null() && holder->IsJSObject()) {
8504 ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name)); 8682 ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name));
8505 JSObject* object = JSObject::cast(*holder); 8683 JSObject* object = JSObject::cast(*holder);
8506 Object* receiver; 8684 Object* receiver;
8507 if (object->IsGlobalObject()) { 8685 if (object->IsGlobalObject()) {
8508 receiver = GlobalObject::cast(object)->global_receiver(); 8686 receiver = GlobalObject::cast(object)->global_receiver();
8509 } else if (context->is_exception_holder(*holder)) { 8687 } else if (context->is_exception_holder(*holder)) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
8555 CONVERT_ARG_CHECKED(Context, context, 1); 8733 CONVERT_ARG_CHECKED(Context, context, 1);
8556 CONVERT_ARG_CHECKED(String, name, 2); 8734 CONVERT_ARG_CHECKED(String, name, 2);
8557 CONVERT_SMI_ARG_CHECKED(strict_unchecked, 3); 8735 CONVERT_SMI_ARG_CHECKED(strict_unchecked, 3);
8558 RUNTIME_ASSERT(strict_unchecked == kStrictMode || 8736 RUNTIME_ASSERT(strict_unchecked == kStrictMode ||
8559 strict_unchecked == kNonStrictMode); 8737 strict_unchecked == kNonStrictMode);
8560 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked); 8738 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
8561 8739
8562 int index; 8740 int index;
8563 PropertyAttributes attributes; 8741 PropertyAttributes attributes;
8564 ContextLookupFlags flags = FOLLOW_CHAINS; 8742 ContextLookupFlags flags = FOLLOW_CHAINS;
8565 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); 8743 BindingFlags binding_flags;
8744 Handle<Object> holder = context->Lookup(name,
8745 flags,
8746 &index,
8747 &attributes,
8748 &binding_flags);
8566 8749
8567 if (index >= 0) { 8750 if (index >= 0) {
8568 if (holder->IsContext()) { 8751 if (holder->IsContext()) {
8752 Handle<Context> context = Handle<Context>::cast(holder);
8753 if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
8754 context->get(index)->IsTheHole()) {
8755 Handle<Object> error =
8756 isolate->factory()->NewReferenceError("not_defined",
8757 HandleVector(&name, 1));
8758 return isolate->Throw(*error);
8759 }
8569 // Ignore if read_only variable. 8760 // Ignore if read_only variable.
8570 if ((attributes & READ_ONLY) == 0) { 8761 if ((attributes & READ_ONLY) == 0) {
8571 // Context is a fixed array and set cannot fail. 8762 // Context is a fixed array and set cannot fail.
8572 Context::cast(*holder)->set(index, *value); 8763 context->set(index, *value);
8573 } else if (strict_mode == kStrictMode) { 8764 } else if (strict_mode == kStrictMode) {
8574 // Setting read only property in strict mode. 8765 // Setting read only property in strict mode.
8575 Handle<Object> error = 8766 Handle<Object> error =
8576 isolate->factory()->NewTypeError("strict_cannot_assign", 8767 isolate->factory()->NewTypeError("strict_cannot_assign",
8577 HandleVector(&name, 1)); 8768 HandleVector(&name, 1));
8578 return isolate->Throw(*error); 8769 return isolate->Throw(*error);
8579 } 8770 }
8580 } else { 8771 } else {
8581 ASSERT((attributes & READ_ONLY) == 0); 8772 ASSERT((attributes & READ_ONLY) == 0);
8582 Handle<Object> result = 8773 Handle<Object> result =
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
9014 // the stack frames to compute the context. 9205 // the stack frames to compute the context.
9015 StackFrameLocator locator; 9206 StackFrameLocator locator;
9016 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 9207 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
9017 ASSERT(Context::cast(frame->context()) == *context); 9208 ASSERT(Context::cast(frame->context()) == *context);
9018 #endif 9209 #endif
9019 9210
9020 // Find where the 'eval' symbol is bound. It is unaliased only if 9211 // Find where the 'eval' symbol is bound. It is unaliased only if
9021 // it is bound in the global context. 9212 // it is bound in the global context.
9022 int index = -1; 9213 int index = -1;
9023 PropertyAttributes attributes = ABSENT; 9214 PropertyAttributes attributes = ABSENT;
9215 BindingFlags binding_flags;
9024 while (true) { 9216 while (true) {
9025 receiver = context->Lookup(isolate->factory()->eval_symbol(), 9217 receiver = context->Lookup(isolate->factory()->eval_symbol(),
9026 FOLLOW_PROTOTYPE_CHAIN, 9218 FOLLOW_PROTOTYPE_CHAIN,
9027 &index, &attributes); 9219 &index,
9220 &attributes,
9221 &binding_flags);
9028 // Stop search when eval is found or when the global context is 9222 // Stop search when eval is found or when the global context is
9029 // reached. 9223 // reached.
9030 if (attributes != ABSENT || context->IsGlobalContext()) break; 9224 if (attributes != ABSENT || context->IsGlobalContext()) break;
9031 context = Handle<Context>(context->previous(), isolate); 9225 context = Handle<Context>(context->previous(), isolate);
9032 } 9226 }
9033 9227
9034 // If eval could not be resolved, it has been deleted and we need to 9228 // If eval could not be resolved, it has been deleted and we need to
9035 // throw a reference error. 9229 // throw a reference error.
9036 if (attributes == ABSENT) { 9230 if (attributes == ABSENT) {
9037 Handle<Object> name = isolate->factory()->eval_symbol(); 9231 Handle<Object> name = isolate->factory()->eval_symbol();
(...skipping 3952 matching lines...) Expand 10 before | Expand all | Expand 10 after
12990 } else { 13184 } else {
12991 // Handle last resort GC and make sure to allow future allocations 13185 // Handle last resort GC and make sure to allow future allocations
12992 // to grow the heap without causing GCs (if possible). 13186 // to grow the heap without causing GCs (if possible).
12993 isolate->counters()->gc_last_resort_from_js()->Increment(); 13187 isolate->counters()->gc_last_resort_from_js()->Increment();
12994 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); 13188 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
12995 } 13189 }
12996 } 13190 }
12997 13191
12998 13192
12999 } } // namespace v8::internal 13193 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | src/runtime.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698