| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |