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 24 matching lines...) Expand all Loading... |
35 #include "bootstrapper.h" | 35 #include "bootstrapper.h" |
36 #include "codegen.h" | 36 #include "codegen.h" |
37 #include "compilation-cache.h" | 37 #include "compilation-cache.h" |
38 #include "compiler.h" | 38 #include "compiler.h" |
39 #include "cpu.h" | 39 #include "cpu.h" |
40 #include "dateparser-inl.h" | 40 #include "dateparser-inl.h" |
41 #include "debug.h" | 41 #include "debug.h" |
42 #include "deoptimizer.h" | 42 #include "deoptimizer.h" |
43 #include "execution.h" | 43 #include "execution.h" |
44 #include "global-handles.h" | 44 #include "global-handles.h" |
| 45 #include "isolate-inl.h" |
45 #include "jsregexp.h" | 46 #include "jsregexp.h" |
46 #include "json-parser.h" | 47 #include "json-parser.h" |
47 #include "liveedit.h" | 48 #include "liveedit.h" |
48 #include "liveobjectlist-inl.h" | 49 #include "liveobjectlist-inl.h" |
49 #include "misc-intrinsics.h" | 50 #include "misc-intrinsics.h" |
50 #include "parser.h" | 51 #include "parser.h" |
51 #include "platform.h" | 52 #include "platform.h" |
52 #include "runtime-profiler.h" | 53 #include "runtime-profiler.h" |
53 #include "runtime.h" | 54 #include "runtime.h" |
54 #include "scopeinfo.h" | 55 #include "scopeinfo.h" |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 if (!maybe_result->ToObject(&result)) return maybe_result; | 171 if (!maybe_result->ToObject(&result)) return maybe_result; |
171 } | 172 } |
172 } | 173 } |
173 } | 174 } |
174 } | 175 } |
175 | 176 |
176 // Deep copy local elements. | 177 // Deep copy local elements. |
177 // Pixel elements cannot be created using an object literal. | 178 // Pixel elements cannot be created using an object literal. |
178 ASSERT(!copy->HasExternalArrayElements()); | 179 ASSERT(!copy->HasExternalArrayElements()); |
179 switch (copy->GetElementsKind()) { | 180 switch (copy->GetElementsKind()) { |
| 181 case FAST_SMI_ONLY_ELEMENTS: |
180 case FAST_ELEMENTS: { | 182 case FAST_ELEMENTS: { |
181 FixedArray* elements = FixedArray::cast(copy->elements()); | 183 FixedArray* elements = FixedArray::cast(copy->elements()); |
182 if (elements->map() == heap->fixed_cow_array_map()) { | 184 if (elements->map() == heap->fixed_cow_array_map()) { |
183 isolate->counters()->cow_arrays_created_runtime()->Increment(); | 185 isolate->counters()->cow_arrays_created_runtime()->Increment(); |
184 #ifdef DEBUG | 186 #ifdef DEBUG |
185 for (int i = 0; i < elements->length(); i++) { | 187 for (int i = 0; i < elements->length(); i++) { |
186 ASSERT(!elements->get(i)->IsJSObject()); | 188 ASSERT(!elements->get(i)->IsJSObject()); |
187 } | 189 } |
188 #endif | 190 #endif |
189 } else { | 191 } else { |
190 for (int i = 0; i < elements->length(); i++) { | 192 for (int i = 0; i < elements->length(); i++) { |
191 Object* value = elements->get(i); | 193 Object* value = elements->get(i); |
| 194 ASSERT(value->IsSmi() || |
| 195 value->IsTheHole() || |
| 196 (copy->GetElementsKind() == FAST_ELEMENTS)); |
192 if (value->IsJSObject()) { | 197 if (value->IsJSObject()) { |
193 JSObject* js_object = JSObject::cast(value); | 198 JSObject* js_object = JSObject::cast(value); |
194 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, | 199 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, |
195 js_object); | 200 js_object); |
196 if (!maybe_result->ToObject(&result)) return maybe_result; | 201 if (!maybe_result->ToObject(&result)) return maybe_result; |
197 } | 202 } |
198 elements->set(i, result); | 203 elements->set(i, result); |
199 } | 204 } |
200 } | 205 } |
201 } | 206 } |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 Handle<JSFunction> constructor( | 430 Handle<JSFunction> constructor( |
426 JSFunction::GlobalContextFromLiterals(*literals)->array_function()); | 431 JSFunction::GlobalContextFromLiterals(*literals)->array_function()); |
427 Handle<Object> object = isolate->factory()->NewJSObject(constructor); | 432 Handle<Object> object = isolate->factory()->NewJSObject(constructor); |
428 | 433 |
429 const bool is_cow = | 434 const bool is_cow = |
430 (elements->map() == isolate->heap()->fixed_cow_array_map()); | 435 (elements->map() == isolate->heap()->fixed_cow_array_map()); |
431 Handle<FixedArray> copied_elements = | 436 Handle<FixedArray> copied_elements = |
432 is_cow ? elements : isolate->factory()->CopyFixedArray(elements); | 437 is_cow ? elements : isolate->factory()->CopyFixedArray(elements); |
433 | 438 |
434 Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements); | 439 Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements); |
| 440 bool has_non_smi = false; |
435 if (is_cow) { | 441 if (is_cow) { |
436 #ifdef DEBUG | |
437 // Copy-on-write arrays must be shallow (and simple). | 442 // Copy-on-write arrays must be shallow (and simple). |
438 for (int i = 0; i < content->length(); i++) { | 443 if (FLAG_smi_only_arrays) { |
439 ASSERT(!content->get(i)->IsFixedArray()); | 444 for (int i = 0; i < content->length(); i++) { |
| 445 Object* current = content->get(i); |
| 446 ASSERT(!current->IsFixedArray()); |
| 447 if (!current->IsSmi() && !current->IsTheHole()) { |
| 448 has_non_smi = true; |
| 449 } |
| 450 } |
| 451 } else { |
| 452 #if DEBUG |
| 453 for (int i = 0; i < content->length(); i++) { |
| 454 ASSERT(!content->get(i)->IsFixedArray()); |
| 455 } |
| 456 #endif |
440 } | 457 } |
441 #endif | |
442 } else { | 458 } else { |
443 for (int i = 0; i < content->length(); i++) { | 459 for (int i = 0; i < content->length(); i++) { |
444 if (content->get(i)->IsFixedArray()) { | 460 Object* current = content->get(i); |
| 461 if (current->IsFixedArray()) { |
445 // The value contains the constant_properties of a | 462 // The value contains the constant_properties of a |
446 // simple object or array literal. | 463 // simple object or array literal. |
447 Handle<FixedArray> fa(FixedArray::cast(content->get(i))); | 464 Handle<FixedArray> fa(FixedArray::cast(content->get(i))); |
448 Handle<Object> result = | 465 Handle<Object> result = |
449 CreateLiteralBoilerplate(isolate, literals, fa); | 466 CreateLiteralBoilerplate(isolate, literals, fa); |
450 if (result.is_null()) return result; | 467 if (result.is_null()) return result; |
451 content->set(i, *result); | 468 content->set(i, *result); |
| 469 has_non_smi = true; |
| 470 } else { |
| 471 if (!current->IsSmi() && !current->IsTheHole()) { |
| 472 has_non_smi = true; |
| 473 } |
452 } | 474 } |
453 } | 475 } |
454 } | 476 } |
455 | 477 |
456 // Set the elements. | 478 // Set the elements. |
457 Handle<JSArray>::cast(object)->SetContent(*content); | 479 Handle<JSArray> js_object(Handle<JSArray>::cast(object)); |
| 480 isolate->factory()->SetContent(js_object, content); |
| 481 |
| 482 if (FLAG_smi_only_arrays) { |
| 483 if (has_non_smi && js_object->HasFastSmiOnlyElements()) { |
| 484 isolate->factory()->EnsureCanContainNonSmiElements(js_object); |
| 485 } |
| 486 } |
| 487 |
458 return object; | 488 return object; |
459 } | 489 } |
460 | 490 |
461 | 491 |
462 static Handle<Object> CreateLiteralBoilerplate( | 492 static Handle<Object> CreateLiteralBoilerplate( |
463 Isolate* isolate, | 493 Isolate* isolate, |
464 Handle<FixedArray> literals, | 494 Handle<FixedArray> literals, |
465 Handle<FixedArray> array) { | 495 Handle<FixedArray> array) { |
466 Handle<FixedArray> elements = CompileTimeValue::GetElements(array); | 496 Handle<FixedArray> elements = CompileTimeValue::GetElements(array); |
467 const bool kHasNoFunctionLiteral = false; | 497 const bool kHasNoFunctionLiteral = false; |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 weakmap->set_table(*table); | 708 weakmap->set_table(*table); |
679 weakmap->set_next(Smi::FromInt(0)); | 709 weakmap->set_next(Smi::FromInt(0)); |
680 return *weakmap; | 710 return *weakmap; |
681 } | 711 } |
682 | 712 |
683 | 713 |
684 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) { | 714 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) { |
685 NoHandleAllocation ha; | 715 NoHandleAllocation ha; |
686 ASSERT(args.length() == 2); | 716 ASSERT(args.length() == 2); |
687 CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0); | 717 CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0); |
688 // TODO(mstarzinger): Currently we cannot use JSProxy objects as keys | 718 CONVERT_ARG_CHECKED(JSReceiver, key, 1); |
689 // because they cannot be cast to JSObject to get an identity hash code. | 719 return ObjectHashTable::cast(weakmap->table())->Lookup(*key); |
690 CONVERT_ARG_CHECKED(JSObject, key, 1); | |
691 return weakmap->table()->Lookup(*key); | |
692 } | 720 } |
693 | 721 |
694 | 722 |
695 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) { | 723 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) { |
696 HandleScope scope(isolate); | 724 HandleScope scope(isolate); |
697 ASSERT(args.length() == 3); | 725 ASSERT(args.length() == 3); |
698 CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0); | 726 CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0); |
699 // TODO(mstarzinger): See Runtime_WeakMapGet above. | 727 CONVERT_ARG_CHECKED(JSReceiver, key, 1); |
700 CONVERT_ARG_CHECKED(JSObject, key, 1); | |
701 Handle<Object> value(args[2]); | 728 Handle<Object> value(args[2]); |
702 Handle<ObjectHashTable> table(weakmap->table()); | 729 Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table())); |
703 Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value); | 730 Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value); |
704 weakmap->set_table(*new_table); | 731 weakmap->set_table(*new_table); |
705 return *value; | 732 return *value; |
706 } | 733 } |
707 | 734 |
708 | 735 |
709 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) { | 736 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) { |
710 NoHandleAllocation ha; | 737 NoHandleAllocation ha; |
711 ASSERT(args.length() == 1); | 738 ASSERT(args.length() == 1); |
712 Object* obj = args[0]; | 739 Object* obj = args[0]; |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1204 // assign to it when evaluating the assignment for "const x = | 1231 // assign to it when evaluating the assignment for "const x = |
1205 // <expr>" the initial value is the hole. | 1232 // <expr>" the initial value is the hole. |
1206 bool is_const_property = value->IsTheHole(); | 1233 bool is_const_property = value->IsTheHole(); |
1207 bool is_function_declaration = false; | 1234 bool is_function_declaration = false; |
1208 if (value->IsUndefined() || is_const_property) { | 1235 if (value->IsUndefined() || is_const_property) { |
1209 // Lookup the property in the global object, and don't set the | 1236 // Lookup the property in the global object, and don't set the |
1210 // value of the variable if the property is already there. | 1237 // value of the variable if the property is already there. |
1211 LookupResult lookup; | 1238 LookupResult lookup; |
1212 global->Lookup(*name, &lookup); | 1239 global->Lookup(*name, &lookup); |
1213 if (lookup.IsProperty()) { | 1240 if (lookup.IsProperty()) { |
1214 // Determine if the property is local by comparing the holder | 1241 // We found an existing property. Unless it was an interceptor |
1215 // against the global object. The information will be used to | 1242 // that claims the property is absent, skip this declaration. |
1216 // avoid throwing re-declaration errors when declaring | 1243 if (lookup.type() != INTERCEPTOR) { |
1217 // variables or constants that exist in the prototype chain. | |
1218 bool is_local = (*global == lookup.holder()); | |
1219 // Get the property attributes and determine if the property is | |
1220 // read-only. | |
1221 PropertyAttributes attributes = global->GetPropertyAttribute(*name); | |
1222 bool is_read_only = (attributes & READ_ONLY) != 0; | |
1223 if (lookup.type() == INTERCEPTOR) { | |
1224 // If the interceptor says the property is there, we | |
1225 // just return undefined without overwriting the property. | |
1226 // Otherwise, we continue to setting the property. | |
1227 if (attributes != ABSENT) { | |
1228 // Check if the existing property conflicts with regards to const. | |
1229 if (is_local && (is_read_only || is_const_property)) { | |
1230 const char* type = (is_read_only) ? "const" : "var"; | |
1231 return ThrowRedeclarationError(isolate, type, name); | |
1232 }; | |
1233 // The property already exists without conflicting: Go to | |
1234 // the next declaration. | |
1235 continue; | |
1236 } | |
1237 // Fall-through and introduce the absent property by using | |
1238 // SetProperty. | |
1239 } else { | |
1240 // For const properties, we treat a callback with this name | |
1241 // even in the prototype as a conflicting declaration. | |
1242 if (is_const_property && (lookup.type() == CALLBACKS)) { | |
1243 return ThrowRedeclarationError(isolate, "const", name); | |
1244 } | |
1245 // Otherwise, we check for locally conflicting declarations. | |
1246 if (is_local && (is_read_only || is_const_property)) { | |
1247 const char* type = (is_read_only) ? "const" : "var"; | |
1248 return ThrowRedeclarationError(isolate, type, name); | |
1249 } | |
1250 // The property already exists without conflicting: Go to | |
1251 // the next declaration. | |
1252 continue; | 1244 continue; |
1253 } | 1245 } |
| 1246 PropertyAttributes attributes = global->GetPropertyAttribute(*name); |
| 1247 if (attributes != ABSENT) { |
| 1248 continue; |
| 1249 } |
| 1250 // Fall-through and introduce the absent property by using |
| 1251 // SetProperty. |
1254 } | 1252 } |
1255 } else { | 1253 } else { |
1256 is_function_declaration = true; | 1254 is_function_declaration = true; |
1257 // Copy the function and update its context. Use it as value. | 1255 // Copy the function and update its context. Use it as value. |
1258 Handle<SharedFunctionInfo> shared = | 1256 Handle<SharedFunctionInfo> shared = |
1259 Handle<SharedFunctionInfo>::cast(value); | 1257 Handle<SharedFunctionInfo>::cast(value); |
1260 Handle<JSFunction> function = | 1258 Handle<JSFunction> function = |
1261 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, | 1259 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, |
1262 context, | 1260 context, |
1263 TENURED); | 1261 TENURED); |
1264 value = function; | 1262 value = function; |
1265 } | 1263 } |
1266 | 1264 |
1267 LookupResult lookup; | 1265 LookupResult lookup; |
1268 global->LocalLookup(*name, &lookup); | 1266 global->LocalLookup(*name, &lookup); |
1269 | 1267 |
1270 // There's a local property that we need to overwrite because | |
1271 // we're either declaring a function or there's an interceptor | |
1272 // that claims the property is absent. | |
1273 // | |
1274 // Check for conflicting re-declarations. We cannot have | |
1275 // conflicting types in case of intercepted properties because | |
1276 // they are absent. | |
1277 if (lookup.IsProperty() && | |
1278 (lookup.type() != INTERCEPTOR) && | |
1279 (lookup.IsReadOnly() || is_const_property)) { | |
1280 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; | |
1281 return ThrowRedeclarationError(isolate, type, name); | |
1282 } | |
1283 | |
1284 // Compute the property attributes. According to ECMA-262, section | 1268 // Compute the property attributes. According to ECMA-262, section |
1285 // 13, page 71, the property must be read-only and | 1269 // 13, page 71, the property must be read-only and |
1286 // non-deletable. However, neither SpiderMonkey nor KJS creates the | 1270 // non-deletable. However, neither SpiderMonkey nor KJS creates the |
1287 // property as read-only, so we don't either. | 1271 // property as read-only, so we don't either. |
1288 int attr = NONE; | 1272 int attr = NONE; |
1289 if ((flags & kDeclareGlobalsEvalFlag) == 0) { | 1273 if ((flags & kDeclareGlobalsEvalFlag) == 0) { |
1290 attr |= DONT_DELETE; | 1274 attr |= DONT_DELETE; |
1291 } | 1275 } |
1292 bool is_native = (flags & kDeclareGlobalsNativeFlag) != 0; | 1276 bool is_native = (flags & kDeclareGlobalsNativeFlag) != 0; |
1293 if (is_const_property || (is_native && is_function_declaration)) { | 1277 if (is_const_property || (is_native && is_function_declaration)) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 | 1312 |
1329 ASSERT(!isolate->has_pending_exception()); | 1313 ASSERT(!isolate->has_pending_exception()); |
1330 return isolate->heap()->undefined_value(); | 1314 return isolate->heap()->undefined_value(); |
1331 } | 1315 } |
1332 | 1316 |
1333 | 1317 |
1334 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { | 1318 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { |
1335 HandleScope scope(isolate); | 1319 HandleScope scope(isolate); |
1336 ASSERT(args.length() == 4); | 1320 ASSERT(args.length() == 4); |
1337 | 1321 |
1338 CONVERT_ARG_CHECKED(Context, context, 0); | 1322 // Declarations are always made in a function or global context. In the |
| 1323 // case of eval code, the context passed is the context of the caller, |
| 1324 // which may be some nested context and not the declaration context. |
| 1325 RUNTIME_ASSERT(args[0]->IsContext()); |
| 1326 Handle<Context> context(Context::cast(args[0])->declaration_context()); |
| 1327 |
1339 Handle<String> name(String::cast(args[1])); | 1328 Handle<String> name(String::cast(args[1])); |
1340 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2)); | 1329 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2)); |
1341 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); | 1330 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); |
1342 Handle<Object> initial_value(args[3], isolate); | 1331 Handle<Object> initial_value(args[3], isolate); |
1343 | 1332 |
1344 // Declarations are always done in a function or global context. | |
1345 context = Handle<Context>(context->declaration_context()); | |
1346 | |
1347 int index; | 1333 int index; |
1348 PropertyAttributes attributes; | 1334 PropertyAttributes attributes; |
1349 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; | 1335 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; |
1350 BindingFlags binding_flags; | 1336 BindingFlags binding_flags; |
1351 Handle<Object> holder = | 1337 Handle<Object> holder = |
1352 context->Lookup(name, flags, &index, &attributes, &binding_flags); | 1338 context->Lookup(name, flags, &index, &attributes, &binding_flags); |
1353 | 1339 |
1354 if (attributes != ABSENT) { | 1340 if (attributes != ABSENT) { |
1355 // The name was declared before; check for conflicting | 1341 // The name was declared before; check for conflicting re-declarations. |
1356 // re-declarations: This is similar to the code in parser.cc in | |
1357 // the AstBuildingParser::Declare function. | |
1358 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) { | 1342 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) { |
1359 // Functions are not read-only. | 1343 // Functions are not read-only. |
1360 ASSERT(mode != READ_ONLY || initial_value->IsTheHole()); | 1344 ASSERT(mode != READ_ONLY || initial_value->IsTheHole()); |
1361 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var"; | 1345 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var"; |
1362 return ThrowRedeclarationError(isolate, type, name); | 1346 return ThrowRedeclarationError(isolate, type, name); |
1363 } | 1347 } |
1364 | 1348 |
1365 // Initialize it if necessary. | 1349 // Initialize it if necessary. |
1366 if (*initial_value != NULL) { | 1350 if (*initial_value != NULL) { |
1367 if (index >= 0) { | 1351 if (index >= 0) { |
1368 // The variable or constant context slot should always be in | 1352 ASSERT(holder.is_identical_to(context)); |
1369 // the function context or the arguments object. | 1353 if (((attributes & READ_ONLY) == 0) || |
1370 if (holder->IsContext()) { | 1354 context->get(index)->IsTheHole()) { |
1371 ASSERT(holder.is_identical_to(context)); | 1355 context->set(index, *initial_value); |
1372 if (((attributes & READ_ONLY) == 0) || | |
1373 context->get(index)->IsTheHole()) { | |
1374 context->set(index, *initial_value); | |
1375 } | |
1376 } else { | |
1377 // The holder is an arguments object. | |
1378 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | |
1379 Handle<Object> result = SetElement(arguments, index, initial_value, | |
1380 kNonStrictMode); | |
1381 if (result.is_null()) return Failure::Exception(); | |
1382 } | 1356 } |
1383 } else { | 1357 } else { |
1384 // Slow case: The property is not in the FixedArray part of the context. | 1358 // Slow case: The property is in the context extension object of a |
1385 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); | 1359 // function context or the global object of a global context. |
| 1360 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
1386 RETURN_IF_EMPTY_HANDLE( | 1361 RETURN_IF_EMPTY_HANDLE( |
1387 isolate, | 1362 isolate, |
1388 SetProperty(context_ext, name, initial_value, | 1363 SetProperty(object, name, initial_value, mode, kNonStrictMode)); |
1389 mode, kNonStrictMode)); | |
1390 } | 1364 } |
1391 } | 1365 } |
1392 | 1366 |
1393 } else { | 1367 } else { |
1394 // The property is not in the function context. It needs to be | 1368 // The property is not in the function context. It needs to be |
1395 // "declared" in the function context's extension context, or in the | 1369 // "declared" in the function context's extension context or as a |
1396 // global context. | 1370 // property of the the global object. |
1397 Handle<JSObject> context_ext; | 1371 Handle<JSObject> object; |
1398 if (context->has_extension()) { | 1372 if (context->has_extension()) { |
1399 // The function context's extension context exists - use it. | 1373 object = Handle<JSObject>(JSObject::cast(context->extension())); |
1400 context_ext = Handle<JSObject>(JSObject::cast(context->extension())); | |
1401 } else { | 1374 } else { |
1402 // The function context's extension context does not exists - allocate | 1375 // Context extension objects are allocated lazily. |
1403 // it. | 1376 ASSERT(context->IsFunctionContext()); |
1404 context_ext = isolate->factory()->NewJSObject( | 1377 object = isolate->factory()->NewJSObject( |
1405 isolate->context_extension_function()); | 1378 isolate->context_extension_function()); |
1406 // And store it in the extension slot. | 1379 context->set_extension(*object); |
1407 context->set_extension(*context_ext); | |
1408 } | 1380 } |
1409 ASSERT(*context_ext != NULL); | 1381 ASSERT(*object != NULL); |
1410 | 1382 |
1411 // Declare the property by setting it to the initial value if provided, | 1383 // Declare the property by setting it to the initial value if provided, |
1412 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for | 1384 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for |
1413 // constant declarations). | 1385 // constant declarations). |
1414 ASSERT(!context_ext->HasLocalProperty(*name)); | 1386 ASSERT(!object->HasLocalProperty(*name)); |
1415 Handle<Object> value(isolate->heap()->undefined_value(), isolate); | 1387 Handle<Object> value(isolate->heap()->undefined_value(), isolate); |
1416 if (*initial_value != NULL) value = initial_value; | 1388 if (*initial_value != NULL) value = initial_value; |
1417 // Declaring a const context slot is a conflicting declaration if | 1389 // Declaring a const context slot is a conflicting declaration if |
1418 // there is a callback with that name in a prototype. It is | 1390 // there is a callback with that name in a prototype. It is |
1419 // allowed to introduce const variables in | 1391 // allowed to introduce const variables in |
1420 // JSContextExtensionObjects. They are treated specially in | 1392 // JSContextExtensionObjects. They are treated specially in |
1421 // SetProperty and no setters are invoked for those since they are | 1393 // SetProperty and no setters are invoked for those since they are |
1422 // not real JSObjects. | 1394 // not real JSObjects. |
1423 if (initial_value->IsTheHole() && | 1395 if (initial_value->IsTheHole() && |
1424 !context_ext->IsJSContextExtensionObject()) { | 1396 !object->IsJSContextExtensionObject()) { |
1425 LookupResult lookup; | 1397 LookupResult lookup; |
1426 context_ext->Lookup(*name, &lookup); | 1398 object->Lookup(*name, &lookup); |
1427 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) { | 1399 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) { |
1428 return ThrowRedeclarationError(isolate, "const", name); | 1400 return ThrowRedeclarationError(isolate, "const", name); |
1429 } | 1401 } |
1430 } | 1402 } |
1431 RETURN_IF_EMPTY_HANDLE(isolate, | 1403 RETURN_IF_EMPTY_HANDLE(isolate, |
1432 SetProperty(context_ext, name, value, mode, | 1404 SetProperty(object, name, value, mode, |
1433 kNonStrictMode)); | 1405 kNonStrictMode)); |
1434 } | 1406 } |
1435 | 1407 |
1436 return isolate->heap()->undefined_value(); | 1408 return isolate->heap()->undefined_value(); |
1437 } | 1409 } |
1438 | 1410 |
1439 | 1411 |
1440 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { | 1412 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { |
1441 NoHandleAllocation nha; | 1413 NoHandleAllocation nha; |
1442 // args[0] == name | 1414 // args[0] == name |
(...skipping 15 matching lines...) Expand all Loading... |
1458 // not be deletable. | 1430 // not be deletable. |
1459 PropertyAttributes attributes = DONT_DELETE; | 1431 PropertyAttributes attributes = DONT_DELETE; |
1460 | 1432 |
1461 // Lookup the property locally in the global object. If it isn't | 1433 // Lookup the property locally in the global object. If it isn't |
1462 // there, there is a property with this name in the prototype chain. | 1434 // there, there is a property with this name in the prototype chain. |
1463 // We follow Safari and Firefox behavior and only set the property | 1435 // We follow Safari and Firefox behavior and only set the property |
1464 // locally if there is an explicit initialization value that we have | 1436 // locally if there is an explicit initialization value that we have |
1465 // to assign to the property. | 1437 // to assign to the property. |
1466 // Note that objects can have hidden prototypes, so we need to traverse | 1438 // Note that objects can have hidden prototypes, so we need to traverse |
1467 // the whole chain of hidden prototypes to do a 'local' lookup. | 1439 // the whole chain of hidden prototypes to do a 'local' lookup. |
1468 JSObject* real_holder = global; | 1440 Object* object = global; |
1469 LookupResult lookup; | 1441 LookupResult lookup; |
1470 while (true) { | 1442 while (object->IsJSObject() && |
1471 real_holder->LocalLookup(*name, &lookup); | 1443 JSObject::cast(object)->map()->is_hidden_prototype()) { |
1472 if (lookup.IsProperty()) { | 1444 JSObject* raw_holder = JSObject::cast(object); |
1473 // Determine if this is a redeclaration of something read-only. | 1445 raw_holder->LocalLookup(*name, &lookup); |
1474 if (lookup.IsReadOnly()) { | 1446 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { |
1475 // If we found readonly property on one of hidden prototypes, | 1447 HandleScope handle_scope(isolate); |
1476 // just shadow it. | 1448 Handle<JSObject> holder(raw_holder); |
1477 if (real_holder != isolate->context()->global()) break; | 1449 PropertyAttributes intercepted = holder->GetPropertyAttribute(*name); |
1478 return ThrowRedeclarationError(isolate, "const", name); | 1450 // Update the raw pointer in case it's changed due to GC. |
1479 } | 1451 raw_holder = *holder; |
1480 | 1452 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { |
1481 // Determine if this is a redeclaration of an intercepted read-only | 1453 // Found an interceptor that's not read only. |
1482 // property and figure out if the property exists at all. | 1454 if (assign) { |
1483 bool found = true; | 1455 return raw_holder->SetProperty( |
1484 PropertyType type = lookup.type(); | 1456 &lookup, *name, args[2], attributes, strict_mode); |
1485 if (type == INTERCEPTOR) { | 1457 } else { |
1486 HandleScope handle_scope(isolate); | 1458 return isolate->heap()->undefined_value(); |
1487 Handle<JSObject> holder(real_holder); | |
1488 PropertyAttributes intercepted = holder->GetPropertyAttribute(*name); | |
1489 real_holder = *holder; | |
1490 if (intercepted == ABSENT) { | |
1491 // The interceptor claims the property isn't there. We need to | |
1492 // make sure to introduce it. | |
1493 found = false; | |
1494 } else if ((intercepted & READ_ONLY) != 0) { | |
1495 // The property is present, but read-only. Since we're trying to | |
1496 // overwrite it with a variable declaration we must throw a | |
1497 // re-declaration error. However if we found readonly property | |
1498 // on one of hidden prototypes, just shadow it. | |
1499 if (real_holder != isolate->context()->global()) break; | |
1500 return ThrowRedeclarationError(isolate, "const", name); | |
1501 } | 1459 } |
1502 } | 1460 } |
1503 | |
1504 if (found && !assign) { | |
1505 // The global property is there and we're not assigning any value | |
1506 // to it. Just return. | |
1507 return isolate->heap()->undefined_value(); | |
1508 } | |
1509 | |
1510 // Assign the value (or undefined) to the property. | |
1511 Object* value = (assign) ? args[2] : isolate->heap()->undefined_value(); | |
1512 return real_holder->SetProperty( | |
1513 &lookup, *name, value, attributes, strict_mode); | |
1514 } | 1461 } |
1515 | 1462 object = raw_holder->GetPrototype(); |
1516 Object* proto = real_holder->GetPrototype(); | |
1517 if (!proto->IsJSObject()) | |
1518 break; | |
1519 | |
1520 if (!JSObject::cast(proto)->map()->is_hidden_prototype()) | |
1521 break; | |
1522 | |
1523 real_holder = JSObject::cast(proto); | |
1524 } | 1463 } |
1525 | 1464 |
| 1465 // Reload global in case the loop above performed a GC. |
1526 global = isolate->context()->global(); | 1466 global = isolate->context()->global(); |
1527 if (assign) { | 1467 if (assign) { |
1528 return global->SetProperty(*name, args[2], attributes, strict_mode); | 1468 return global->SetProperty(*name, args[2], attributes, strict_mode); |
1529 } | 1469 } |
1530 return isolate->heap()->undefined_value(); | 1470 return isolate->heap()->undefined_value(); |
1531 } | 1471 } |
1532 | 1472 |
1533 | 1473 |
1534 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { | 1474 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { |
1535 // All constants are declared with an initial value. The name | 1475 // All constants are declared with an initial value. The name |
(...skipping 17 matching lines...) Expand all Loading... |
1553 // prototype chain (this rules out using SetProperty). | 1493 // prototype chain (this rules out using SetProperty). |
1554 // We use SetLocalPropertyIgnoreAttributes instead | 1494 // We use SetLocalPropertyIgnoreAttributes instead |
1555 LookupResult lookup; | 1495 LookupResult lookup; |
1556 global->LocalLookup(*name, &lookup); | 1496 global->LocalLookup(*name, &lookup); |
1557 if (!lookup.IsProperty()) { | 1497 if (!lookup.IsProperty()) { |
1558 return global->SetLocalPropertyIgnoreAttributes(*name, | 1498 return global->SetLocalPropertyIgnoreAttributes(*name, |
1559 *value, | 1499 *value, |
1560 attributes); | 1500 attributes); |
1561 } | 1501 } |
1562 | 1502 |
1563 // Determine if this is a redeclaration of something not | |
1564 // read-only. In case the result is hidden behind an interceptor we | |
1565 // need to ask it for the property attributes. | |
1566 if (!lookup.IsReadOnly()) { | 1503 if (!lookup.IsReadOnly()) { |
1567 if (lookup.type() != INTERCEPTOR) { | |
1568 return ThrowRedeclarationError(isolate, "var", name); | |
1569 } | |
1570 | |
1571 PropertyAttributes intercepted = global->GetPropertyAttribute(*name); | |
1572 | |
1573 // Throw re-declaration error if the intercepted property is present | |
1574 // but not read-only. | |
1575 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { | |
1576 return ThrowRedeclarationError(isolate, "var", name); | |
1577 } | |
1578 | |
1579 // Restore global object from context (in case of GC) and continue | 1504 // Restore global object from context (in case of GC) and continue |
1580 // with setting the value because the property is either absent or | 1505 // with setting the value. |
1581 // read-only. We also have to do redo the lookup. | |
1582 HandleScope handle_scope(isolate); | 1506 HandleScope handle_scope(isolate); |
1583 Handle<GlobalObject> global(isolate->context()->global()); | 1507 Handle<GlobalObject> global(isolate->context()->global()); |
1584 | 1508 |
1585 // BUG 1213575: Handle the case where we have to set a read-only | 1509 // BUG 1213575: Handle the case where we have to set a read-only |
1586 // property through an interceptor and only do it if it's | 1510 // property through an interceptor and only do it if it's |
1587 // uninitialized, e.g. the hole. Nirk... | 1511 // uninitialized, e.g. the hole. Nirk... |
1588 // Passing non-strict mode because the property is writable. | 1512 // Passing non-strict mode because the property is writable. |
1589 RETURN_IF_EMPTY_HANDLE(isolate, | 1513 RETURN_IF_EMPTY_HANDLE(isolate, |
1590 SetProperty(global, | 1514 SetProperty(global, |
1591 name, | 1515 name, |
1592 value, | 1516 value, |
1593 attributes, | 1517 attributes, |
1594 kNonStrictMode)); | 1518 kNonStrictMode)); |
1595 return *value; | 1519 return *value; |
1596 } | 1520 } |
1597 | 1521 |
1598 // Set the value, but only we're assigning the initial value to a | 1522 // Set the value, but only if we're assigning the initial value to a |
1599 // constant. For now, we determine this by checking if the | 1523 // constant. For now, we determine this by checking if the |
1600 // current value is the hole. | 1524 // current value is the hole. |
1601 // Strict mode handling not needed (const disallowed in strict mode). | 1525 // Strict mode handling not needed (const is disallowed in strict mode). |
1602 PropertyType type = lookup.type(); | 1526 PropertyType type = lookup.type(); |
1603 if (type == FIELD) { | 1527 if (type == FIELD) { |
1604 FixedArray* properties = global->properties(); | 1528 FixedArray* properties = global->properties(); |
1605 int index = lookup.GetFieldIndex(); | 1529 int index = lookup.GetFieldIndex(); |
1606 if (properties->get(index)->IsTheHole()) { | 1530 if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) { |
1607 properties->set(index, *value); | 1531 properties->set(index, *value); |
1608 } | 1532 } |
1609 } else if (type == NORMAL) { | 1533 } else if (type == NORMAL) { |
1610 if (global->GetNormalizedProperty(&lookup)->IsTheHole()) { | 1534 if (global->GetNormalizedProperty(&lookup)->IsTheHole() || |
| 1535 !lookup.IsReadOnly()) { |
1611 global->SetNormalizedProperty(&lookup, *value); | 1536 global->SetNormalizedProperty(&lookup, *value); |
1612 } | 1537 } |
1613 } else { | 1538 } else { |
1614 // Ignore re-initialization of constants that have already been | 1539 // Ignore re-initialization of constants that have already been |
1615 // assigned a function value. | 1540 // assigned a function value. |
1616 ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION); | 1541 ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION); |
1617 } | 1542 } |
1618 | 1543 |
1619 // Use the set value as the result of the operation. | 1544 // Use the set value as the result of the operation. |
1620 return *value; | 1545 return *value; |
1621 } | 1546 } |
1622 | 1547 |
1623 | 1548 |
1624 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { | 1549 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { |
1625 HandleScope scope(isolate); | 1550 HandleScope scope(isolate); |
1626 ASSERT(args.length() == 3); | 1551 ASSERT(args.length() == 3); |
1627 | 1552 |
1628 Handle<Object> value(args[0], isolate); | 1553 Handle<Object> value(args[0], isolate); |
1629 ASSERT(!value->IsTheHole()); | 1554 ASSERT(!value->IsTheHole()); |
1630 CONVERT_ARG_CHECKED(Context, context, 1); | |
1631 Handle<String> name(String::cast(args[2])); | |
1632 | 1555 |
1633 // Initializations are always done in a function or global context. | 1556 // Initializations are always done in a function or global context. |
1634 context = Handle<Context>(context->declaration_context()); | 1557 RUNTIME_ASSERT(args[1]->IsContext()); |
| 1558 Handle<Context> context(Context::cast(args[1])->declaration_context()); |
| 1559 |
| 1560 Handle<String> name(String::cast(args[2])); |
1635 | 1561 |
1636 int index; | 1562 int index; |
1637 PropertyAttributes attributes; | 1563 PropertyAttributes attributes; |
1638 ContextLookupFlags flags = FOLLOW_CHAINS; | 1564 ContextLookupFlags flags = FOLLOW_CHAINS; |
1639 BindingFlags binding_flags; | 1565 BindingFlags binding_flags; |
1640 Handle<Object> holder = | 1566 Handle<Object> holder = |
1641 context->Lookup(name, flags, &index, &attributes, &binding_flags); | 1567 context->Lookup(name, flags, &index, &attributes, &binding_flags); |
1642 | 1568 |
1643 // In most situations, the property introduced by the const | |
1644 // declaration should be present in the context extension object. | |
1645 // However, because declaration and initialization are separate, the | |
1646 // property might have been deleted (if it was introduced by eval) | |
1647 // before we reach the initialization point. | |
1648 // | |
1649 // Example: | |
1650 // | |
1651 // function f() { eval("delete x; const x;"); } | |
1652 // | |
1653 // In that case, the initialization behaves like a normal assignment | |
1654 // to property 'x'. | |
1655 if (index >= 0) { | 1569 if (index >= 0) { |
1656 if (holder->IsContext()) { | 1570 ASSERT(holder->IsContext()); |
1657 // Property was found in a context. Perform the assignment if we | 1571 // Property was found in a context. Perform the assignment if we |
1658 // found some non-constant or an uninitialized constant. | 1572 // found some non-constant or an uninitialized constant. |
1659 Handle<Context> context = Handle<Context>::cast(holder); | 1573 Handle<Context> context = Handle<Context>::cast(holder); |
1660 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) { | 1574 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) { |
1661 context->set(index, *value); | 1575 context->set(index, *value); |
1662 } | |
1663 } else { | |
1664 // The holder is an arguments object. | |
1665 ASSERT((attributes & READ_ONLY) == 0); | |
1666 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | |
1667 RETURN_IF_EMPTY_HANDLE( | |
1668 isolate, | |
1669 SetElement(arguments, index, value, kNonStrictMode)); | |
1670 } | 1576 } |
1671 return *value; | 1577 return *value; |
1672 } | 1578 } |
1673 | 1579 |
1674 // The property could not be found, we introduce it in the global | 1580 // The property could not be found, we introduce it as a property of the |
1675 // context. | 1581 // global object. |
1676 if (attributes == ABSENT) { | 1582 if (attributes == ABSENT) { |
1677 Handle<JSObject> global = Handle<JSObject>( | 1583 Handle<JSObject> global = Handle<JSObject>( |
1678 isolate->context()->global()); | 1584 isolate->context()->global()); |
1679 // Strict mode not needed (const disallowed in strict mode). | 1585 // Strict mode not needed (const disallowed in strict mode). |
1680 RETURN_IF_EMPTY_HANDLE( | 1586 RETURN_IF_EMPTY_HANDLE( |
1681 isolate, | 1587 isolate, |
1682 SetProperty(global, name, value, NONE, kNonStrictMode)); | 1588 SetProperty(global, name, value, NONE, kNonStrictMode)); |
1683 return *value; | 1589 return *value; |
1684 } | 1590 } |
1685 | 1591 |
1686 // The property was present in a context extension object. | 1592 // The property was present in some function's context extension object, |
1687 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); | 1593 // as a property on the subject of a with, or as a property of the global |
| 1594 // object. |
| 1595 // |
| 1596 // In most situations, eval-introduced consts should still be present in |
| 1597 // the context extension object. However, because declaration and |
| 1598 // initialization are separate, the property might have been deleted |
| 1599 // before we reach the initialization point. |
| 1600 // |
| 1601 // Example: |
| 1602 // |
| 1603 // function f() { eval("delete x; const x;"); } |
| 1604 // |
| 1605 // In that case, the initialization behaves like a normal assignment. |
| 1606 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
1688 | 1607 |
1689 if (*context_ext == context->extension()) { | 1608 if (*object == context->extension()) { |
1690 // This is the property that was introduced by the const | 1609 // This is the property that was introduced by the const declaration. |
1691 // declaration. Set it if it hasn't been set before. NOTE: We | 1610 // Set it if it hasn't been set before. NOTE: We cannot use |
1692 // cannot use GetProperty() to get the current value as it | 1611 // GetProperty() to get the current value as it 'unholes' the value. |
1693 // 'unholes' the value. | |
1694 LookupResult lookup; | 1612 LookupResult lookup; |
1695 context_ext->LocalLookupRealNamedProperty(*name, &lookup); | 1613 object->LocalLookupRealNamedProperty(*name, &lookup); |
1696 ASSERT(lookup.IsProperty()); // the property was declared | 1614 ASSERT(lookup.IsProperty()); // the property was declared |
1697 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only | 1615 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only |
1698 | 1616 |
1699 PropertyType type = lookup.type(); | 1617 PropertyType type = lookup.type(); |
1700 if (type == FIELD) { | 1618 if (type == FIELD) { |
1701 FixedArray* properties = context_ext->properties(); | 1619 FixedArray* properties = object->properties(); |
1702 int index = lookup.GetFieldIndex(); | 1620 int index = lookup.GetFieldIndex(); |
1703 if (properties->get(index)->IsTheHole()) { | 1621 if (properties->get(index)->IsTheHole()) { |
1704 properties->set(index, *value); | 1622 properties->set(index, *value); |
1705 } | 1623 } |
1706 } else if (type == NORMAL) { | 1624 } else if (type == NORMAL) { |
1707 if (context_ext->GetNormalizedProperty(&lookup)->IsTheHole()) { | 1625 if (object->GetNormalizedProperty(&lookup)->IsTheHole()) { |
1708 context_ext->SetNormalizedProperty(&lookup, *value); | 1626 object->SetNormalizedProperty(&lookup, *value); |
1709 } | 1627 } |
1710 } else { | 1628 } else { |
1711 // We should not reach here. Any real, named property should be | 1629 // We should not reach here. Any real, named property should be |
1712 // either a field or a dictionary slot. | 1630 // either a field or a dictionary slot. |
1713 UNREACHABLE(); | 1631 UNREACHABLE(); |
1714 } | 1632 } |
1715 } else { | 1633 } else { |
1716 // The property was found in a different context extension object. | 1634 // The property was found on some other object. Set it if it is not a |
1717 // Set it if it is not a read-only property. | 1635 // read-only property. |
1718 if ((attributes & READ_ONLY) == 0) { | 1636 if ((attributes & READ_ONLY) == 0) { |
1719 // Strict mode not needed (const disallowed in strict mode). | 1637 // Strict mode not needed (const disallowed in strict mode). |
1720 RETURN_IF_EMPTY_HANDLE( | 1638 RETURN_IF_EMPTY_HANDLE( |
1721 isolate, | 1639 isolate, |
1722 SetProperty(context_ext, name, value, attributes, kNonStrictMode)); | 1640 SetProperty(object, name, value, attributes, kNonStrictMode)); |
1723 } | 1641 } |
1724 } | 1642 } |
1725 | 1643 |
1726 return *value; | 1644 return *value; |
1727 } | 1645 } |
1728 | 1646 |
1729 | 1647 |
1730 RUNTIME_FUNCTION(MaybeObject*, | 1648 RUNTIME_FUNCTION(MaybeObject*, |
1731 Runtime_OptimizeObjectForAddingMultipleProperties) { | 1649 Runtime_OptimizeObjectForAddingMultipleProperties) { |
1732 HandleScope scope(isolate); | 1650 HandleScope scope(isolate); |
1733 ASSERT(args.length() == 2); | 1651 ASSERT(args.length() == 2); |
1734 CONVERT_ARG_CHECKED(JSObject, object, 0); | 1652 CONVERT_ARG_CHECKED(JSObject, object, 0); |
1735 CONVERT_SMI_ARG_CHECKED(properties, 1); | 1653 CONVERT_SMI_ARG_CHECKED(properties, 1); |
1736 if (object->HasFastProperties()) { | 1654 if (object->HasFastProperties()) { |
1737 NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); | 1655 NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); |
1738 } | 1656 } |
1739 return *object; | 1657 return *object; |
1740 } | 1658 } |
1741 | 1659 |
1742 | 1660 |
| 1661 RUNTIME_FUNCTION(MaybeObject*, Runtime_NonSmiElementStored) { |
| 1662 ASSERT(args.length() == 1); |
| 1663 CONVERT_ARG_CHECKED(JSObject, object, 0); |
| 1664 if (FLAG_smi_only_arrays && object->HasFastSmiOnlyElements()) { |
| 1665 MaybeObject* maybe_map = object->GetElementsTransitionMap(FAST_ELEMENTS); |
| 1666 Map* map; |
| 1667 if (!maybe_map->To<Map>(&map)) return maybe_map; |
| 1668 object->set_map(Map::cast(map)); |
| 1669 } |
| 1670 return *object; |
| 1671 } |
| 1672 |
| 1673 |
1743 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { | 1674 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { |
1744 HandleScope scope(isolate); | 1675 HandleScope scope(isolate); |
1745 ASSERT(args.length() == 4); | 1676 ASSERT(args.length() == 4); |
1746 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); | 1677 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); |
1747 CONVERT_ARG_CHECKED(String, subject, 1); | 1678 CONVERT_ARG_CHECKED(String, subject, 1); |
1748 // Due to the way the JS calls are constructed this must be less than the | 1679 // Due to the way the JS calls are constructed this must be less than the |
1749 // length of a string, i.e. it is always a Smi. We check anyway for security. | 1680 // length of a string, i.e. it is always a Smi. We check anyway for security. |
1750 CONVERT_SMI_ARG_CHECKED(index, 2); | 1681 CONVERT_SMI_ARG_CHECKED(index, 2); |
1751 CONVERT_ARG_CHECKED(JSArray, last_match_info, 3); | 1682 CONVERT_ARG_CHECKED(JSArray, last_match_info, 3); |
1752 RUNTIME_ASSERT(last_match_info->HasFastElements()); | 1683 RUNTIME_ASSERT(last_match_info->HasFastElements()); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1818 JSFunction::cast(constructor)->initial_map() == map) { | 1749 JSFunction::cast(constructor)->initial_map() == map) { |
1819 // If we still have the original map, set in-object properties directly. | 1750 // If we still have the original map, set in-object properties directly. |
1820 regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source); | 1751 regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source); |
1821 // TODO(lrn): Consider skipping write barrier on booleans as well. | 1752 // TODO(lrn): Consider skipping write barrier on booleans as well. |
1822 // Both true and false should be in oldspace at all times. | 1753 // Both true and false should be in oldspace at all times. |
1823 regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, global); | 1754 regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, global); |
1824 regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, ignoreCase); | 1755 regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, ignoreCase); |
1825 regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, multiline); | 1756 regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, multiline); |
1826 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, | 1757 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, |
1827 Smi::FromInt(0), | 1758 Smi::FromInt(0), |
1828 SKIP_WRITE_BARRIER); | 1759 SKIP_WRITE_BARRIER); // It's a Smi. |
1829 return regexp; | 1760 return regexp; |
1830 } | 1761 } |
1831 | 1762 |
1832 // Map has changed, so use generic, but slower, method. | 1763 // Map has changed, so use generic, but slower, method. |
1833 PropertyAttributes final = | 1764 PropertyAttributes final = |
1834 static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE); | 1765 static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE); |
1835 PropertyAttributes writable = | 1766 PropertyAttributes writable = |
1836 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); | 1767 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); |
1837 Heap* heap = isolate->heap(); | 1768 Heap* heap = isolate->heap(); |
1838 MaybeObject* result; | 1769 MaybeObject* result; |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 int number_of_literals = fun->NumberOfLiterals(); | 2163 int number_of_literals = fun->NumberOfLiterals(); |
2233 Handle<FixedArray> literals = | 2164 Handle<FixedArray> literals = |
2234 isolate->factory()->NewFixedArray(number_of_literals, TENURED); | 2165 isolate->factory()->NewFixedArray(number_of_literals, TENURED); |
2235 if (number_of_literals > 0) { | 2166 if (number_of_literals > 0) { |
2236 // Insert the object, regexp and array functions in the literals | 2167 // Insert the object, regexp and array functions in the literals |
2237 // array prefix. These are the functions that will be used when | 2168 // array prefix. These are the functions that will be used when |
2238 // creating object, regexp and array literals. | 2169 // creating object, regexp and array literals. |
2239 literals->set(JSFunction::kLiteralGlobalContextIndex, | 2170 literals->set(JSFunction::kLiteralGlobalContextIndex, |
2240 context->global_context()); | 2171 context->global_context()); |
2241 } | 2172 } |
2242 // It's okay to skip the write barrier here because the literals | 2173 target->set_literals(*literals); |
2243 // are guaranteed to be in old space. | |
2244 target->set_literals(*literals, SKIP_WRITE_BARRIER); | |
2245 target->set_next_function_link(isolate->heap()->undefined_value()); | 2174 target->set_next_function_link(isolate->heap()->undefined_value()); |
2246 | 2175 |
2247 if (isolate->logger()->is_logging() || CpuProfiler::is_profiling(isolate)) { | 2176 if (isolate->logger()->is_logging() || CpuProfiler::is_profiling(isolate)) { |
2248 isolate->logger()->LogExistingFunction( | 2177 isolate->logger()->LogExistingFunction( |
2249 shared, Handle<Code>(shared->code())); | 2178 shared, Handle<Code>(shared->code())); |
2250 } | 2179 } |
2251 } | 2180 } |
2252 | 2181 |
2253 target->set_context(*context); | 2182 target->set_context(*context); |
2254 return *target; | 2183 return *target; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2318 NoHandleAllocation ha; | 2247 NoHandleAllocation ha; |
2319 ASSERT(args.length() == 1); | 2248 ASSERT(args.length() == 1); |
2320 return CharFromCode(isolate, args[0]); | 2249 return CharFromCode(isolate, args[0]); |
2321 } | 2250 } |
2322 | 2251 |
2323 | 2252 |
2324 class FixedArrayBuilder { | 2253 class FixedArrayBuilder { |
2325 public: | 2254 public: |
2326 explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity) | 2255 explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity) |
2327 : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)), | 2256 : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)), |
2328 length_(0) { | 2257 length_(0), |
| 2258 has_non_smi_elements_(false) { |
2329 // Require a non-zero initial size. Ensures that doubling the size to | 2259 // Require a non-zero initial size. Ensures that doubling the size to |
2330 // extend the array will work. | 2260 // extend the array will work. |
2331 ASSERT(initial_capacity > 0); | 2261 ASSERT(initial_capacity > 0); |
2332 } | 2262 } |
2333 | 2263 |
2334 explicit FixedArrayBuilder(Handle<FixedArray> backing_store) | 2264 explicit FixedArrayBuilder(Handle<FixedArray> backing_store) |
2335 : array_(backing_store), | 2265 : array_(backing_store), |
2336 length_(0) { | 2266 length_(0), |
| 2267 has_non_smi_elements_(false) { |
2337 // Require a non-zero initial size. Ensures that doubling the size to | 2268 // Require a non-zero initial size. Ensures that doubling the size to |
2338 // extend the array will work. | 2269 // extend the array will work. |
2339 ASSERT(backing_store->length() > 0); | 2270 ASSERT(backing_store->length() > 0); |
2340 } | 2271 } |
2341 | 2272 |
2342 bool HasCapacity(int elements) { | 2273 bool HasCapacity(int elements) { |
2343 int length = array_->length(); | 2274 int length = array_->length(); |
2344 int required_length = length_ + elements; | 2275 int required_length = length_ + elements; |
2345 return (length >= required_length); | 2276 return (length >= required_length); |
2346 } | 2277 } |
2347 | 2278 |
2348 void EnsureCapacity(int elements) { | 2279 void EnsureCapacity(int elements) { |
2349 int length = array_->length(); | 2280 int length = array_->length(); |
2350 int required_length = length_ + elements; | 2281 int required_length = length_ + elements; |
2351 if (length < required_length) { | 2282 if (length < required_length) { |
2352 int new_length = length; | 2283 int new_length = length; |
2353 do { | 2284 do { |
2354 new_length *= 2; | 2285 new_length *= 2; |
2355 } while (new_length < required_length); | 2286 } while (new_length < required_length); |
2356 Handle<FixedArray> extended_array = | 2287 Handle<FixedArray> extended_array = |
2357 array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length); | 2288 array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length); |
2358 array_->CopyTo(0, *extended_array, 0, length_); | 2289 array_->CopyTo(0, *extended_array, 0, length_); |
2359 array_ = extended_array; | 2290 array_ = extended_array; |
2360 } | 2291 } |
2361 } | 2292 } |
2362 | 2293 |
2363 void Add(Object* value) { | 2294 void Add(Object* value) { |
| 2295 ASSERT(!value->IsSmi()); |
2364 ASSERT(length_ < capacity()); | 2296 ASSERT(length_ < capacity()); |
2365 array_->set(length_, value); | 2297 array_->set(length_, value); |
2366 length_++; | 2298 length_++; |
| 2299 has_non_smi_elements_ = true; |
2367 } | 2300 } |
2368 | 2301 |
2369 void Add(Smi* value) { | 2302 void Add(Smi* value) { |
| 2303 ASSERT(value->IsSmi()); |
2370 ASSERT(length_ < capacity()); | 2304 ASSERT(length_ < capacity()); |
2371 array_->set(length_, value); | 2305 array_->set(length_, value); |
2372 length_++; | 2306 length_++; |
2373 } | 2307 } |
2374 | 2308 |
2375 Handle<FixedArray> array() { | 2309 Handle<FixedArray> array() { |
2376 return array_; | 2310 return array_; |
2377 } | 2311 } |
2378 | 2312 |
2379 int length() { | 2313 int length() { |
2380 return length_; | 2314 return length_; |
2381 } | 2315 } |
2382 | 2316 |
2383 int capacity() { | 2317 int capacity() { |
2384 return array_->length(); | 2318 return array_->length(); |
2385 } | 2319 } |
2386 | 2320 |
2387 Handle<JSArray> ToJSArray() { | 2321 Handle<JSArray> ToJSArray() { |
2388 Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_); | 2322 Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_); |
2389 result_array->set_length(Smi::FromInt(length_)); | 2323 result_array->set_length(Smi::FromInt(length_)); |
2390 return result_array; | 2324 return result_array; |
2391 } | 2325 } |
2392 | 2326 |
2393 Handle<JSArray> ToJSArray(Handle<JSArray> target_array) { | 2327 Handle<JSArray> ToJSArray(Handle<JSArray> target_array) { |
2394 target_array->set_elements(*array_); | 2328 FACTORY->SetContent(target_array, array_); |
2395 target_array->set_length(Smi::FromInt(length_)); | 2329 target_array->set_length(Smi::FromInt(length_)); |
2396 return target_array; | 2330 return target_array; |
2397 } | 2331 } |
2398 | 2332 |
2399 private: | 2333 private: |
2400 Handle<FixedArray> array_; | 2334 Handle<FixedArray> array_; |
2401 int length_; | 2335 int length_; |
| 2336 bool has_non_smi_elements_; |
2402 }; | 2337 }; |
2403 | 2338 |
2404 | 2339 |
2405 // Forward declarations. | 2340 // Forward declarations. |
2406 const int kStringBuilderConcatHelperLengthBits = 11; | 2341 const int kStringBuilderConcatHelperLengthBits = 11; |
2407 const int kStringBuilderConcatHelperPositionBits = 19; | 2342 const int kStringBuilderConcatHelperPositionBits = 19; |
2408 | 2343 |
2409 template <typename schar> | 2344 template <typename schar> |
2410 static inline void StringBuilderConcatHelper(String*, | 2345 static inline void StringBuilderConcatHelper(String*, |
2411 schar*, | 2346 schar*, |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2886 } | 2821 } |
2887 } else { | 2822 } else { |
2888 FindStringIndices(isolate, | 2823 FindStringIndices(isolate, |
2889 subject_vector, | 2824 subject_vector, |
2890 pattern_content.ToUC16Vector(), | 2825 pattern_content.ToUC16Vector(), |
2891 indices, | 2826 indices, |
2892 limit); | 2827 limit); |
2893 } | 2828 } |
2894 } else { | 2829 } else { |
2895 Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); | 2830 Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); |
2896 if (pattern->IsAsciiRepresentation()) { | 2831 if (pattern_content.IsAscii()) { |
2897 FindStringIndices(isolate, | 2832 FindStringIndices(isolate, |
2898 subject_vector, | 2833 subject_vector, |
2899 pattern_content.ToAsciiVector(), | 2834 pattern_content.ToAsciiVector(), |
2900 indices, | 2835 indices, |
2901 limit); | 2836 limit); |
2902 } else { | 2837 } else { |
2903 FindStringIndices(isolate, | 2838 FindStringIndices(isolate, |
2904 subject_vector, | 2839 subject_vector, |
2905 pattern_content.ToUC16Vector(), | 2840 pattern_content.ToUC16Vector(), |
2906 indices, | 2841 indices, |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3012 ZoneScope zone(isolate, DELETE_ON_EXIT); | 2947 ZoneScope zone(isolate, DELETE_ON_EXIT); |
3013 CompiledReplacement compiled_replacement; | 2948 CompiledReplacement compiled_replacement; |
3014 compiled_replacement.Compile(replacement_handle, | 2949 compiled_replacement.Compile(replacement_handle, |
3015 capture_count, | 2950 capture_count, |
3016 length); | 2951 length); |
3017 | 2952 |
3018 bool is_global = regexp_handle->GetFlags().is_global(); | 2953 bool is_global = regexp_handle->GetFlags().is_global(); |
3019 | 2954 |
3020 // Shortcut for simple non-regexp global replacements | 2955 // Shortcut for simple non-regexp global replacements |
3021 if (is_global && | 2956 if (is_global && |
3022 regexp->TypeTag() == JSRegExp::ATOM && | 2957 regexp_handle->TypeTag() == JSRegExp::ATOM && |
3023 compiled_replacement.simple_hint()) { | 2958 compiled_replacement.simple_hint()) { |
3024 if (subject_handle->HasOnlyAsciiChars() && | 2959 if (subject_handle->HasOnlyAsciiChars() && |
3025 replacement_handle->HasOnlyAsciiChars()) { | 2960 replacement_handle->HasOnlyAsciiChars()) { |
3026 return StringReplaceStringWithString<SeqAsciiString>( | 2961 return StringReplaceStringWithString<SeqAsciiString>( |
3027 isolate, subject_handle, regexp_handle, replacement_handle); | 2962 isolate, subject_handle, regexp_handle, replacement_handle); |
3028 } else { | 2963 } else { |
3029 return StringReplaceStringWithString<SeqTwoByteString>( | 2964 return StringReplaceStringWithString<SeqTwoByteString>( |
3030 isolate, subject_handle, regexp_handle, replacement_handle); | 2965 isolate, subject_handle, regexp_handle, replacement_handle); |
3031 } | 2966 } |
3032 } | 2967 } |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3235 // Shorten string and fill | 3170 // Shorten string and fill |
3236 int string_size = ResultSeqString::SizeFor(position); | 3171 int string_size = ResultSeqString::SizeFor(position); |
3237 int allocated_string_size = ResultSeqString::SizeFor(new_length); | 3172 int allocated_string_size = ResultSeqString::SizeFor(new_length); |
3238 int delta = allocated_string_size - string_size; | 3173 int delta = allocated_string_size - string_size; |
3239 | 3174 |
3240 answer->set_length(position); | 3175 answer->set_length(position); |
3241 if (delta == 0) return *answer; | 3176 if (delta == 0) return *answer; |
3242 | 3177 |
3243 Address end_of_string = answer->address() + string_size; | 3178 Address end_of_string = answer->address() + string_size; |
3244 isolate->heap()->CreateFillerObjectAt(end_of_string, delta); | 3179 isolate->heap()->CreateFillerObjectAt(end_of_string, delta); |
| 3180 if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) { |
| 3181 MemoryChunk::IncrementLiveBytes(answer->address(), -delta); |
| 3182 } |
3245 | 3183 |
3246 return *answer; | 3184 return *answer; |
3247 } | 3185 } |
3248 | 3186 |
3249 | 3187 |
3250 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) { | 3188 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) { |
3251 ASSERT(args.length() == 4); | 3189 ASSERT(args.length() == 4); |
3252 | 3190 |
3253 CONVERT_CHECKED(String, subject, args[0]); | 3191 CONVERT_CHECKED(String, subject, args[0]); |
3254 if (!subject->IsFlat()) { | 3192 if (!subject->IsFlat()) { |
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3994 // Character array used for conversion. | 3932 // Character array used for conversion. |
3995 static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz"; | 3933 static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz"; |
3996 return isolate->heap()-> | 3934 return isolate->heap()-> |
3997 LookupSingleCharacterStringFromCode(kCharTable[value]); | 3935 LookupSingleCharacterStringFromCode(kCharTable[value]); |
3998 } | 3936 } |
3999 } | 3937 } |
4000 | 3938 |
4001 // Slow case. | 3939 // Slow case. |
4002 CONVERT_DOUBLE_ARG_CHECKED(value, 0); | 3940 CONVERT_DOUBLE_ARG_CHECKED(value, 0); |
4003 if (isnan(value)) { | 3941 if (isnan(value)) { |
4004 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); | 3942 return *isolate->factory()->nan_symbol(); |
4005 } | 3943 } |
4006 if (isinf(value)) { | 3944 if (isinf(value)) { |
4007 if (value < 0) { | 3945 if (value < 0) { |
4008 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); | 3946 return *isolate->factory()->minus_infinity_symbol(); |
4009 } | 3947 } |
4010 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); | 3948 return *isolate->factory()->infinity_symbol(); |
4011 } | 3949 } |
4012 char* str = DoubleToRadixCString(value, radix); | 3950 char* str = DoubleToRadixCString(value, radix); |
4013 MaybeObject* result = | 3951 MaybeObject* result = |
4014 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); | 3952 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); |
4015 DeleteArray(str); | 3953 DeleteArray(str); |
4016 return result; | 3954 return result; |
4017 } | 3955 } |
4018 | 3956 |
4019 | 3957 |
4020 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) { | 3958 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) { |
4021 NoHandleAllocation ha; | 3959 NoHandleAllocation ha; |
4022 ASSERT(args.length() == 2); | 3960 ASSERT(args.length() == 2); |
4023 | 3961 |
4024 CONVERT_DOUBLE_ARG_CHECKED(value, 0); | 3962 CONVERT_DOUBLE_ARG_CHECKED(value, 0); |
4025 if (isnan(value)) { | 3963 if (isnan(value)) { |
4026 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); | 3964 return *isolate->factory()->nan_symbol(); |
4027 } | 3965 } |
4028 if (isinf(value)) { | 3966 if (isinf(value)) { |
4029 if (value < 0) { | 3967 if (value < 0) { |
4030 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); | 3968 return *isolate->factory()->minus_infinity_symbol(); |
4031 } | 3969 } |
4032 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); | 3970 return *isolate->factory()->infinity_symbol(); |
4033 } | 3971 } |
4034 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); | 3972 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); |
4035 int f = FastD2I(f_number); | 3973 int f = FastD2I(f_number); |
4036 RUNTIME_ASSERT(f >= 0); | 3974 RUNTIME_ASSERT(f >= 0); |
4037 char* str = DoubleToFixedCString(value, f); | 3975 char* str = DoubleToFixedCString(value, f); |
4038 MaybeObject* res = | 3976 MaybeObject* res = |
4039 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); | 3977 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); |
4040 DeleteArray(str); | 3978 DeleteArray(str); |
4041 return res; | 3979 return res; |
4042 } | 3980 } |
4043 | 3981 |
4044 | 3982 |
4045 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) { | 3983 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) { |
4046 NoHandleAllocation ha; | 3984 NoHandleAllocation ha; |
4047 ASSERT(args.length() == 2); | 3985 ASSERT(args.length() == 2); |
4048 | 3986 |
4049 CONVERT_DOUBLE_ARG_CHECKED(value, 0); | 3987 CONVERT_DOUBLE_ARG_CHECKED(value, 0); |
4050 if (isnan(value)) { | 3988 if (isnan(value)) { |
4051 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); | 3989 return *isolate->factory()->nan_symbol(); |
4052 } | 3990 } |
4053 if (isinf(value)) { | 3991 if (isinf(value)) { |
4054 if (value < 0) { | 3992 if (value < 0) { |
4055 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); | 3993 return *isolate->factory()->minus_infinity_symbol(); |
4056 } | 3994 } |
4057 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); | 3995 return *isolate->factory()->infinity_symbol(); |
4058 } | 3996 } |
4059 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); | 3997 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); |
4060 int f = FastD2I(f_number); | 3998 int f = FastD2I(f_number); |
4061 RUNTIME_ASSERT(f >= -1 && f <= 20); | 3999 RUNTIME_ASSERT(f >= -1 && f <= 20); |
4062 char* str = DoubleToExponentialCString(value, f); | 4000 char* str = DoubleToExponentialCString(value, f); |
4063 MaybeObject* res = | 4001 MaybeObject* res = |
4064 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); | 4002 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); |
4065 DeleteArray(str); | 4003 DeleteArray(str); |
4066 return res; | 4004 return res; |
4067 } | 4005 } |
4068 | 4006 |
4069 | 4007 |
4070 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) { | 4008 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) { |
4071 NoHandleAllocation ha; | 4009 NoHandleAllocation ha; |
4072 ASSERT(args.length() == 2); | 4010 ASSERT(args.length() == 2); |
4073 | 4011 |
4074 CONVERT_DOUBLE_ARG_CHECKED(value, 0); | 4012 CONVERT_DOUBLE_ARG_CHECKED(value, 0); |
4075 if (isnan(value)) { | 4013 if (isnan(value)) { |
4076 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); | 4014 return *isolate->factory()->nan_symbol(); |
4077 } | 4015 } |
4078 if (isinf(value)) { | 4016 if (isinf(value)) { |
4079 if (value < 0) { | 4017 if (value < 0) { |
4080 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); | 4018 return *isolate->factory()->minus_infinity_symbol(); |
4081 } | 4019 } |
4082 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); | 4020 return *isolate->factory()->infinity_symbol(); |
4083 } | 4021 } |
4084 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); | 4022 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); |
4085 int f = FastD2I(f_number); | 4023 int f = FastD2I(f_number); |
4086 RUNTIME_ASSERT(f >= 1 && f <= 21); | 4024 RUNTIME_ASSERT(f >= 1 && f <= 21); |
4087 char* str = DoubleToPrecisionCString(value, f); | 4025 char* str = DoubleToPrecisionCString(value, f); |
4088 MaybeObject* res = | 4026 MaybeObject* res = |
4089 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); | 4027 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); |
4090 DeleteArray(str); | 4028 DeleteArray(str); |
4091 return res; | 4029 return res; |
4092 } | 4030 } |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4262 // Steps 9c & 12 - replace an existing data property with an accessor property. | 4200 // Steps 9c & 12 - replace an existing data property with an accessor property. |
4263 // Step 12 - update an existing accessor property with an accessor or generic | 4201 // Step 12 - update an existing accessor property with an accessor or generic |
4264 // descriptor. | 4202 // descriptor. |
4265 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) { | 4203 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) { |
4266 ASSERT(args.length() == 5); | 4204 ASSERT(args.length() == 5); |
4267 HandleScope scope(isolate); | 4205 HandleScope scope(isolate); |
4268 CONVERT_ARG_CHECKED(JSObject, obj, 0); | 4206 CONVERT_ARG_CHECKED(JSObject, obj, 0); |
4269 CONVERT_CHECKED(String, name, args[1]); | 4207 CONVERT_CHECKED(String, name, args[1]); |
4270 CONVERT_CHECKED(Smi, flag_setter, args[2]); | 4208 CONVERT_CHECKED(Smi, flag_setter, args[2]); |
4271 Object* fun = args[3]; | 4209 Object* fun = args[3]; |
4272 RUNTIME_ASSERT(fun->IsJSFunction() || fun->IsUndefined()); | 4210 RUNTIME_ASSERT(fun->IsSpecFunction() || fun->IsUndefined()); |
4273 CONVERT_CHECKED(Smi, flag_attr, args[4]); | 4211 CONVERT_CHECKED(Smi, flag_attr, args[4]); |
4274 int unchecked = flag_attr->value(); | 4212 int unchecked = flag_attr->value(); |
4275 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 4213 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
4276 RUNTIME_ASSERT(!obj->IsNull()); | 4214 RUNTIME_ASSERT(!obj->IsNull()); |
4277 LookupResult result; | 4215 LookupResult result; |
4278 obj->LocalLookupRealNamedProperty(name, &result); | 4216 obj->LocalLookupRealNamedProperty(name, &result); |
4279 | 4217 |
4280 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 4218 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); |
4281 // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION | 4219 // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION |
4282 // delete it to avoid running into trouble in DefineAccessor, which | 4220 // delete it to avoid running into trouble in DefineAccessor, which |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4430 HandleScope scope(isolate); | 4368 HandleScope scope(isolate); |
4431 | 4369 |
4432 if (object->IsUndefined() || object->IsNull()) { | 4370 if (object->IsUndefined() || object->IsNull()) { |
4433 Handle<Object> args[2] = { key, object }; | 4371 Handle<Object> args[2] = { key, object }; |
4434 Handle<Object> error = | 4372 Handle<Object> error = |
4435 isolate->factory()->NewTypeError("non_object_property_store", | 4373 isolate->factory()->NewTypeError("non_object_property_store", |
4436 HandleVector(args, 2)); | 4374 HandleVector(args, 2)); |
4437 return isolate->Throw(*error); | 4375 return isolate->Throw(*error); |
4438 } | 4376 } |
4439 | 4377 |
| 4378 if (object->IsJSProxy()) { |
| 4379 bool has_pending_exception = false; |
| 4380 Handle<Object> name = Execution::ToString(key, &has_pending_exception); |
| 4381 if (has_pending_exception) return Failure::Exception(); |
| 4382 return JSProxy::cast(*object)->SetProperty( |
| 4383 String::cast(*name), *value, attr, strict_mode); |
| 4384 } |
| 4385 |
4440 // If the object isn't a JavaScript object, we ignore the store. | 4386 // If the object isn't a JavaScript object, we ignore the store. |
4441 if (!object->IsJSObject()) return *value; | 4387 if (!object->IsJSObject()) return *value; |
4442 | 4388 |
4443 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 4389 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
4444 | 4390 |
4445 // Check if the given key is an array index. | 4391 // Check if the given key is an array index. |
4446 uint32_t index; | 4392 uint32_t index; |
4447 if (key->ToArrayIndex(&index)) { | 4393 if (key->ToArrayIndex(&index)) { |
4448 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters | 4394 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters |
4449 // of a string using [] notation. We need to support this too in | 4395 // of a string using [] notation. We need to support this too in |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4549 } | 4495 } |
4550 | 4496 |
4551 | 4497 |
4552 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate, | 4498 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate, |
4553 Handle<JSReceiver> receiver, | 4499 Handle<JSReceiver> receiver, |
4554 Handle<Object> key) { | 4500 Handle<Object> key) { |
4555 HandleScope scope(isolate); | 4501 HandleScope scope(isolate); |
4556 | 4502 |
4557 // Check if the given key is an array index. | 4503 // Check if the given key is an array index. |
4558 uint32_t index; | 4504 uint32_t index; |
4559 if (receiver->IsJSObject() && key->ToArrayIndex(&index)) { | 4505 if (key->ToArrayIndex(&index)) { |
4560 // In Firefox/SpiderMonkey, Safari and Opera you can access the | 4506 // In Firefox/SpiderMonkey, Safari and Opera you can access the |
4561 // characters of a string using [] notation. In the case of a | 4507 // characters of a string using [] notation. In the case of a |
4562 // String object we just need to redirect the deletion to the | 4508 // String object we just need to redirect the deletion to the |
4563 // underlying string if the index is in range. Since the | 4509 // underlying string if the index is in range. Since the |
4564 // underlying string does nothing with the deletion, we can ignore | 4510 // underlying string does nothing with the deletion, we can ignore |
4565 // such deletions. | 4511 // such deletions. |
4566 if (receiver->IsStringObjectWithCharacterAt(index)) { | 4512 if (receiver->IsStringObjectWithCharacterAt(index)) { |
4567 return isolate->heap()->true_value(); | 4513 return isolate->heap()->true_value(); |
4568 } | 4514 } |
4569 | 4515 |
4570 return JSObject::cast(*receiver)->DeleteElement( | 4516 return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION); |
4571 index, JSReceiver::FORCE_DELETION); | |
4572 } | 4517 } |
4573 | 4518 |
4574 Handle<String> key_string; | 4519 Handle<String> key_string; |
4575 if (key->IsString()) { | 4520 if (key->IsString()) { |
4576 key_string = Handle<String>::cast(key); | 4521 key_string = Handle<String>::cast(key); |
4577 } else { | 4522 } else { |
4578 // Call-back into JavaScript to convert the key to a string. | 4523 // Call-back into JavaScript to convert the key to a string. |
4579 bool has_pending_exception = false; | 4524 bool has_pending_exception = false; |
4580 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); | 4525 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); |
4581 if (has_pending_exception) return Failure::Exception(); | 4526 if (has_pending_exception) return Failure::Exception(); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4723 return isolate->heap()->true_value(); | 4668 return isolate->heap()->true_value(); |
4724 } | 4669 } |
4725 } | 4670 } |
4726 return isolate->heap()->false_value(); | 4671 return isolate->heap()->false_value(); |
4727 } | 4672 } |
4728 | 4673 |
4729 | 4674 |
4730 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) { | 4675 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) { |
4731 NoHandleAllocation na; | 4676 NoHandleAllocation na; |
4732 ASSERT(args.length() == 2); | 4677 ASSERT(args.length() == 2); |
| 4678 CONVERT_CHECKED(JSReceiver, receiver, args[0]); |
| 4679 CONVERT_CHECKED(String, key, args[1]); |
4733 | 4680 |
4734 // Only JS receivers can have properties. | 4681 bool result = receiver->HasProperty(key); |
4735 if (args[0]->IsJSReceiver()) { | 4682 if (isolate->has_pending_exception()) return Failure::Exception(); |
4736 JSReceiver* receiver = JSReceiver::cast(args[0]); | 4683 return isolate->heap()->ToBoolean(result); |
4737 CONVERT_CHECKED(String, key, args[1]); | |
4738 if (receiver->HasProperty(key)) return isolate->heap()->true_value(); | |
4739 } | |
4740 return isolate->heap()->false_value(); | |
4741 } | 4684 } |
4742 | 4685 |
4743 | 4686 |
4744 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) { | 4687 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) { |
4745 NoHandleAllocation na; | 4688 NoHandleAllocation na; |
4746 ASSERT(args.length() == 2); | 4689 ASSERT(args.length() == 2); |
| 4690 CONVERT_CHECKED(JSReceiver, receiver, args[0]); |
| 4691 CONVERT_CHECKED(Smi, index, args[1]); |
4747 | 4692 |
4748 // Only JS objects can have elements. | 4693 bool result = receiver->HasElement(index->value()); |
4749 if (args[0]->IsJSObject()) { | 4694 if (isolate->has_pending_exception()) return Failure::Exception(); |
4750 JSObject* object = JSObject::cast(args[0]); | 4695 return isolate->heap()->ToBoolean(result); |
4751 CONVERT_CHECKED(Smi, index_obj, args[1]); | |
4752 uint32_t index = index_obj->value(); | |
4753 if (object->HasElement(index)) return isolate->heap()->true_value(); | |
4754 } | |
4755 return isolate->heap()->false_value(); | |
4756 } | 4696 } |
4757 | 4697 |
4758 | 4698 |
4759 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { | 4699 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { |
4760 NoHandleAllocation ha; | 4700 NoHandleAllocation ha; |
4761 ASSERT(args.length() == 2); | 4701 ASSERT(args.length() == 2); |
4762 | 4702 |
4763 CONVERT_CHECKED(JSObject, object, args[0]); | 4703 CONVERT_CHECKED(JSObject, object, args[0]); |
4764 CONVERT_CHECKED(String, key, args[1]); | 4704 CONVERT_CHECKED(String, key, args[1]); |
4765 | 4705 |
4766 uint32_t index; | 4706 uint32_t index; |
4767 if (key->AsArrayIndex(&index)) { | 4707 if (key->AsArrayIndex(&index)) { |
4768 return isolate->heap()->ToBoolean(object->HasElement(index)); | 4708 JSObject::LocalElementType type = object->HasLocalElement(index); |
| 4709 switch (type) { |
| 4710 case JSObject::UNDEFINED_ELEMENT: |
| 4711 case JSObject::STRING_CHARACTER_ELEMENT: |
| 4712 return isolate->heap()->false_value(); |
| 4713 case JSObject::INTERCEPTED_ELEMENT: |
| 4714 case JSObject::FAST_ELEMENT: |
| 4715 return isolate->heap()->true_value(); |
| 4716 case JSObject::DICTIONARY_ELEMENT: { |
| 4717 if (object->IsJSGlobalProxy()) { |
| 4718 Object* proto = object->GetPrototype(); |
| 4719 if (proto->IsNull()) { |
| 4720 return isolate->heap()->false_value(); |
| 4721 } |
| 4722 ASSERT(proto->IsJSGlobalObject()); |
| 4723 object = JSObject::cast(proto); |
| 4724 } |
| 4725 FixedArray* elements = FixedArray::cast(object->elements()); |
| 4726 NumberDictionary* dictionary = NULL; |
| 4727 if (elements->map() == |
| 4728 isolate->heap()->non_strict_arguments_elements_map()) { |
| 4729 dictionary = NumberDictionary::cast(elements->get(1)); |
| 4730 } else { |
| 4731 dictionary = NumberDictionary::cast(elements); |
| 4732 } |
| 4733 int entry = dictionary->FindEntry(index); |
| 4734 ASSERT(entry != NumberDictionary::kNotFound); |
| 4735 PropertyDetails details = dictionary->DetailsAt(entry); |
| 4736 return isolate->heap()->ToBoolean(!details.IsDontEnum()); |
| 4737 } |
| 4738 } |
4769 } | 4739 } |
4770 | 4740 |
4771 PropertyAttributes att = object->GetLocalPropertyAttribute(key); | 4741 PropertyAttributes att = object->GetLocalPropertyAttribute(key); |
4772 return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0); | 4742 return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0); |
4773 } | 4743 } |
4774 | 4744 |
4775 | 4745 |
4776 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) { | 4746 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) { |
4777 HandleScope scope(isolate); | 4747 HandleScope scope(isolate); |
4778 ASSERT(args.length() == 1); | 4748 ASSERT(args.length() == 1); |
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5572 } | 5542 } |
5573 MaybeObject* new_alloc = AllocateRawString<StringType>(isolate, | 5543 MaybeObject* new_alloc = AllocateRawString<StringType>(isolate, |
5574 quoted_length); | 5544 quoted_length); |
5575 Object* new_object; | 5545 Object* new_object; |
5576 if (!new_alloc->ToObject(&new_object)) { | 5546 if (!new_alloc->ToObject(&new_object)) { |
5577 return new_alloc; | 5547 return new_alloc; |
5578 } | 5548 } |
5579 StringType* new_string = StringType::cast(new_object); | 5549 StringType* new_string = StringType::cast(new_object); |
5580 | 5550 |
5581 Char* write_cursor = reinterpret_cast<Char*>( | 5551 Char* write_cursor = reinterpret_cast<Char*>( |
5582 new_string->address() + SeqAsciiString::kHeaderSize); | 5552 new_string->address() + SeqString::kHeaderSize); |
5583 if (comma) *(write_cursor++) = ','; | 5553 if (comma) *(write_cursor++) = ','; |
5584 *(write_cursor++) = '"'; | 5554 *(write_cursor++) = '"'; |
5585 | 5555 |
5586 read_cursor = characters.start(); | 5556 read_cursor = characters.start(); |
5587 while (read_cursor < end) { | 5557 while (read_cursor < end) { |
5588 Char c = *(read_cursor++); | 5558 Char c = *(read_cursor++); |
5589 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | 5559 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { |
5590 *(write_cursor++) = c; | 5560 *(write_cursor++) = c; |
5591 } else { | 5561 } else { |
5592 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; | 5562 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5660 if (!isolate->heap()->new_space()->Contains(new_object)) { | 5630 if (!isolate->heap()->new_space()->Contains(new_object)) { |
5661 // Even if our string is small enough to fit in new space we still have to | 5631 // Even if our string is small enough to fit in new space we still have to |
5662 // handle it being allocated in old space as may happen in the third | 5632 // handle it being allocated in old space as may happen in the third |
5663 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in | 5633 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in |
5664 // CEntryStub::GenerateCore. | 5634 // CEntryStub::GenerateCore. |
5665 return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters); | 5635 return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters); |
5666 } | 5636 } |
5667 StringType* new_string = StringType::cast(new_object); | 5637 StringType* new_string = StringType::cast(new_object); |
5668 ASSERT(isolate->heap()->new_space()->Contains(new_string)); | 5638 ASSERT(isolate->heap()->new_space()->Contains(new_string)); |
5669 | 5639 |
5670 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | |
5671 Char* write_cursor = reinterpret_cast<Char*>( | 5640 Char* write_cursor = reinterpret_cast<Char*>( |
5672 new_string->address() + SeqAsciiString::kHeaderSize); | 5641 new_string->address() + SeqString::kHeaderSize); |
5673 if (comma) *(write_cursor++) = ','; | 5642 if (comma) *(write_cursor++) = ','; |
5674 write_cursor = WriteQuoteJsonString<Char, Char>(isolate, | 5643 write_cursor = WriteQuoteJsonString<Char, Char>(isolate, |
5675 write_cursor, | 5644 write_cursor, |
5676 characters); | 5645 characters); |
5677 int final_length = static_cast<int>( | 5646 int final_length = static_cast<int>( |
5678 write_cursor - reinterpret_cast<Char*>( | 5647 write_cursor - reinterpret_cast<Char*>( |
5679 new_string->address() + SeqAsciiString::kHeaderSize)); | 5648 new_string->address() + SeqString::kHeaderSize)); |
5680 isolate->heap()->new_space()-> | 5649 isolate->heap()->new_space()-> |
5681 template ShrinkStringAtAllocationBoundary<StringType>( | 5650 template ShrinkStringAtAllocationBoundary<StringType>( |
5682 new_string, final_length); | 5651 new_string, final_length); |
5683 return new_string; | 5652 return new_string; |
5684 } | 5653 } |
5685 | 5654 |
5686 | 5655 |
5687 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) { | 5656 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) { |
5688 NoHandleAllocation ha; | 5657 NoHandleAllocation ha; |
5689 CONVERT_CHECKED(String, str, args[0]); | 5658 CONVERT_CHECKED(String, str, args[0]); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5747 // Even if our string is small enough to fit in new space we still have to | 5716 // Even if our string is small enough to fit in new space we still have to |
5748 // handle it being allocated in old space as may happen in the third | 5717 // handle it being allocated in old space as may happen in the third |
5749 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in | 5718 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in |
5750 // CEntryStub::GenerateCore. | 5719 // CEntryStub::GenerateCore. |
5751 return isolate->heap()->undefined_value(); | 5720 return isolate->heap()->undefined_value(); |
5752 } | 5721 } |
5753 AssertNoAllocation no_gc; | 5722 AssertNoAllocation no_gc; |
5754 StringType* new_string = StringType::cast(new_object); | 5723 StringType* new_string = StringType::cast(new_object); |
5755 ASSERT(isolate->heap()->new_space()->Contains(new_string)); | 5724 ASSERT(isolate->heap()->new_space()->Contains(new_string)); |
5756 | 5725 |
5757 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | |
5758 Char* write_cursor = reinterpret_cast<Char*>( | 5726 Char* write_cursor = reinterpret_cast<Char*>( |
5759 new_string->address() + SeqAsciiString::kHeaderSize); | 5727 new_string->address() + SeqString::kHeaderSize); |
5760 *(write_cursor++) = '['; | 5728 *(write_cursor++) = '['; |
5761 for (int i = 0; i < length; i++) { | 5729 for (int i = 0; i < length; i++) { |
5762 if (i != 0) *(write_cursor++) = ','; | 5730 if (i != 0) *(write_cursor++) = ','; |
5763 String* str = String::cast(array->get(i)); | 5731 String* str = String::cast(array->get(i)); |
5764 String::FlatContent content = str->GetFlatContent(); | 5732 String::FlatContent content = str->GetFlatContent(); |
5765 ASSERT(content.IsFlat()); | 5733 ASSERT(content.IsFlat()); |
5766 if (content.IsTwoByte()) { | 5734 if (content.IsTwoByte()) { |
5767 write_cursor = WriteQuoteJsonString<Char, uc16>(isolate, | 5735 write_cursor = WriteQuoteJsonString<Char, uc16>(isolate, |
5768 write_cursor, | 5736 write_cursor, |
5769 content.ToUC16Vector()); | 5737 content.ToUC16Vector()); |
5770 } else { | 5738 } else { |
5771 write_cursor = WriteQuoteJsonString<Char, char>(isolate, | 5739 write_cursor = WriteQuoteJsonString<Char, char>(isolate, |
5772 write_cursor, | 5740 write_cursor, |
5773 content.ToAsciiVector()); | 5741 content.ToAsciiVector()); |
5774 } | 5742 } |
5775 } | 5743 } |
5776 *(write_cursor++) = ']'; | 5744 *(write_cursor++) = ']'; |
5777 | 5745 |
5778 int final_length = static_cast<int>( | 5746 int final_length = static_cast<int>( |
5779 write_cursor - reinterpret_cast<Char*>( | 5747 write_cursor - reinterpret_cast<Char*>( |
5780 new_string->address() + SeqAsciiString::kHeaderSize)); | 5748 new_string->address() + SeqString::kHeaderSize)); |
5781 isolate->heap()->new_space()-> | 5749 isolate->heap()->new_space()-> |
5782 template ShrinkStringAtAllocationBoundary<StringType>( | 5750 template ShrinkStringAtAllocationBoundary<StringType>( |
5783 new_string, final_length); | 5751 new_string, final_length); |
5784 return new_string; | 5752 return new_string; |
5785 } | 5753 } |
5786 | 5754 |
5787 | 5755 |
5788 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) { | 5756 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) { |
5789 NoHandleAllocation ha; | 5757 NoHandleAllocation ha; |
5790 ASSERT(args.length() == 1); | 5758 ASSERT(args.length() == 1); |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6222 if (static_cast<uint32_t>(indices.length()) < limit) { | 6190 if (static_cast<uint32_t>(indices.length()) < limit) { |
6223 indices.Add(subject_length); | 6191 indices.Add(subject_length); |
6224 } | 6192 } |
6225 | 6193 |
6226 // The list indices now contains the end of each part to create. | 6194 // The list indices now contains the end of each part to create. |
6227 | 6195 |
6228 // Create JSArray of substrings separated by separator. | 6196 // Create JSArray of substrings separated by separator. |
6229 int part_count = indices.length(); | 6197 int part_count = indices.length(); |
6230 | 6198 |
6231 Handle<JSArray> result = isolate->factory()->NewJSArray(part_count); | 6199 Handle<JSArray> result = isolate->factory()->NewJSArray(part_count); |
| 6200 MaybeObject* maybe_result = result->EnsureCanContainNonSmiElements(); |
| 6201 if (maybe_result->IsFailure()) return maybe_result; |
6232 result->set_length(Smi::FromInt(part_count)); | 6202 result->set_length(Smi::FromInt(part_count)); |
6233 | 6203 |
6234 ASSERT(result->HasFastElements()); | 6204 ASSERT(result->HasFastElements()); |
6235 | 6205 |
6236 if (part_count == 1 && indices.at(0) == subject_length) { | 6206 if (part_count == 1 && indices.at(0) == subject_length) { |
6237 FixedArray::cast(result->elements())->set(0, *subject); | 6207 FixedArray::cast(result->elements())->set(0, *subject); |
6238 return *result; | 6208 return *result; |
6239 } | 6209 } |
6240 | 6210 |
6241 Handle<FixedArray> elements(FixedArray::cast(result->elements())); | 6211 Handle<FixedArray> elements(FixedArray::cast(result->elements())); |
(...skipping 26 matching lines...) Expand all Loading... |
6268 // not in the cache and fills the remainder with smi zeros. Returns | 6238 // not in the cache and fills the remainder with smi zeros. Returns |
6269 // the length of the successfully copied prefix. | 6239 // the length of the successfully copied prefix. |
6270 static int CopyCachedAsciiCharsToArray(Heap* heap, | 6240 static int CopyCachedAsciiCharsToArray(Heap* heap, |
6271 const char* chars, | 6241 const char* chars, |
6272 FixedArray* elements, | 6242 FixedArray* elements, |
6273 int length) { | 6243 int length) { |
6274 AssertNoAllocation no_gc; | 6244 AssertNoAllocation no_gc; |
6275 FixedArray* ascii_cache = heap->single_character_string_cache(); | 6245 FixedArray* ascii_cache = heap->single_character_string_cache(); |
6276 Object* undefined = heap->undefined_value(); | 6246 Object* undefined = heap->undefined_value(); |
6277 int i; | 6247 int i; |
| 6248 WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc); |
6278 for (i = 0; i < length; ++i) { | 6249 for (i = 0; i < length; ++i) { |
6279 Object* value = ascii_cache->get(chars[i]); | 6250 Object* value = ascii_cache->get(chars[i]); |
6280 if (value == undefined) break; | 6251 if (value == undefined) break; |
6281 ASSERT(!heap->InNewSpace(value)); | 6252 elements->set(i, value, mode); |
6282 elements->set(i, value, SKIP_WRITE_BARRIER); | |
6283 } | 6253 } |
6284 if (i < length) { | 6254 if (i < length) { |
6285 ASSERT(Smi::FromInt(0) == 0); | 6255 ASSERT(Smi::FromInt(0) == 0); |
6286 memset(elements->data_start() + i, 0, kPointerSize * (length - i)); | 6256 memset(elements->data_start() + i, 0, kPointerSize * (length - i)); |
6287 } | 6257 } |
6288 #ifdef DEBUG | 6258 #ifdef DEBUG |
6289 for (int j = 0; j < length; ++j) { | 6259 for (int j = 0; j < length; ++j) { |
6290 Object* element = elements->get(j); | 6260 Object* element = elements->get(j); |
6291 ASSERT(element == Smi::FromInt(0) || | 6261 ASSERT(element == Smi::FromInt(0) || |
6292 (element->IsString() && String::cast(element)->LooksValid())); | 6262 (element->IsString() && String::cast(element)->LooksValid())); |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6596 if (!args[1]->IsSmi()) { | 6566 if (!args[1]->IsSmi()) { |
6597 isolate->context()->mark_out_of_memory(); | 6567 isolate->context()->mark_out_of_memory(); |
6598 return Failure::OutOfMemoryException(); | 6568 return Failure::OutOfMemoryException(); |
6599 } | 6569 } |
6600 int array_length = args.smi_at(1); | 6570 int array_length = args.smi_at(1); |
6601 CONVERT_CHECKED(String, special, args[2]); | 6571 CONVERT_CHECKED(String, special, args[2]); |
6602 | 6572 |
6603 // This assumption is used by the slice encoding in one or two smis. | 6573 // This assumption is used by the slice encoding in one or two smis. |
6604 ASSERT(Smi::kMaxValue >= String::kMaxLength); | 6574 ASSERT(Smi::kMaxValue >= String::kMaxLength); |
6605 | 6575 |
| 6576 MaybeObject* maybe_result = array->EnsureCanContainNonSmiElements(); |
| 6577 if (maybe_result->IsFailure()) return maybe_result; |
| 6578 |
6606 int special_length = special->length(); | 6579 int special_length = special->length(); |
6607 if (!array->HasFastElements()) { | 6580 if (!array->HasFastElements()) { |
6608 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); | 6581 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); |
6609 } | 6582 } |
6610 FixedArray* fixed_array = FixedArray::cast(array->elements()); | 6583 FixedArray* fixed_array = FixedArray::cast(array->elements()); |
6611 if (fixed_array->length() < array_length) { | 6584 if (fixed_array->length() < array_length) { |
6612 array_length = fixed_array->length(); | 6585 array_length = fixed_array->length(); |
6613 } | 6586 } |
6614 | 6587 |
6615 if (array_length == 0) { | 6588 if (array_length == 0) { |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6823 } | 6796 } |
6824 } | 6797 } |
6825 ASSERT(cursor <= buffer.length()); | 6798 ASSERT(cursor <= buffer.length()); |
6826 } | 6799 } |
6827 | 6800 |
6828 | 6801 |
6829 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { | 6802 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { |
6830 NoHandleAllocation ha; | 6803 NoHandleAllocation ha; |
6831 ASSERT(args.length() == 3); | 6804 ASSERT(args.length() == 3); |
6832 CONVERT_CHECKED(JSArray, elements_array, args[0]); | 6805 CONVERT_CHECKED(JSArray, elements_array, args[0]); |
6833 RUNTIME_ASSERT(elements_array->HasFastElements()); | 6806 RUNTIME_ASSERT(elements_array->HasFastElements() || |
| 6807 elements_array->HasFastSmiOnlyElements()); |
6834 CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]); | 6808 CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]); |
6835 CONVERT_CHECKED(String, separator, args[2]); | 6809 CONVERT_CHECKED(String, separator, args[2]); |
6836 // elements_array is fast-mode JSarray of alternating positions | 6810 // elements_array is fast-mode JSarray of alternating positions |
6837 // (increasing order) and strings. | 6811 // (increasing order) and strings. |
6838 // array_length is length of original array (used to add separators); | 6812 // array_length is length of original array (used to add separators); |
6839 // separator is string to put between elements. Assumed to be non-empty. | 6813 // separator is string to put between elements. Assumed to be non-empty. |
6840 | 6814 |
6841 // Find total length of join result. | 6815 // Find total length of join result. |
6842 int string_length = 0; | 6816 int string_length = 0; |
6843 bool is_ascii = true; | 6817 bool is_ascii = true; |
(...skipping 1146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7990 HandleScope scope(isolate); | 7964 HandleScope scope(isolate); |
7991 ASSERT(args.length() == 2); | 7965 ASSERT(args.length() == 2); |
7992 // First argument is a function to use as a constructor. | 7966 // First argument is a function to use as a constructor. |
7993 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 7967 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
7994 | 7968 |
7995 // Second argument is either null or an array of bound arguments. | 7969 // Second argument is either null or an array of bound arguments. |
7996 Handle<FixedArray> bound_args; | 7970 Handle<FixedArray> bound_args; |
7997 int bound_argc = 0; | 7971 int bound_argc = 0; |
7998 if (!args[1]->IsNull()) { | 7972 if (!args[1]->IsNull()) { |
7999 CONVERT_ARG_CHECKED(JSArray, params, 1); | 7973 CONVERT_ARG_CHECKED(JSArray, params, 1); |
8000 RUNTIME_ASSERT(params->HasFastElements()); | 7974 RUNTIME_ASSERT(params->HasFastTypeElements()); |
8001 bound_args = Handle<FixedArray>(FixedArray::cast(params->elements())); | 7975 bound_args = Handle<FixedArray>(FixedArray::cast(params->elements())); |
8002 bound_argc = Smi::cast(params->length())->value(); | 7976 bound_argc = Smi::cast(params->length())->value(); |
8003 } | 7977 } |
8004 | 7978 |
8005 int total_argc = 0; | 7979 int total_argc = 0; |
8006 SmartArrayPointer<Object**> param_data = | 7980 SmartArrayPointer<Object**> param_data = |
8007 GetNonBoundArguments(bound_argc, &total_argc); | 7981 GetNonBoundArguments(bound_argc, &total_argc); |
8008 for (int i = 0; i < bound_argc; i++) { | 7982 for (int i = 0; i < bound_argc; i++) { |
8009 Handle<Object> val = Handle<Object>(bound_args->get(i)); | 7983 Handle<Object> val = Handle<Object>(bound_args->get(i)); |
8010 param_data[i] = val.location(); | 7984 param_data[i] = val.location(); |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8300 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 8274 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
8301 if (!function->IsOptimizable()) return isolate->heap()->undefined_value(); | 8275 if (!function->IsOptimizable()) return isolate->heap()->undefined_value(); |
8302 function->MarkForLazyRecompilation(); | 8276 function->MarkForLazyRecompilation(); |
8303 return isolate->heap()->undefined_value(); | 8277 return isolate->heap()->undefined_value(); |
8304 } | 8278 } |
8305 | 8279 |
8306 | 8280 |
8307 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) { | 8281 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) { |
8308 HandleScope scope(isolate); | 8282 HandleScope scope(isolate); |
8309 ASSERT(args.length() == 1); | 8283 ASSERT(args.length() == 1); |
| 8284 // The least significant bit (after untagging) indicates whether the |
| 8285 // function is currently optimized, regardless of reason. |
8310 if (!V8::UseCrankshaft()) { | 8286 if (!V8::UseCrankshaft()) { |
8311 return Smi::FromInt(4); // 4 == "never". | 8287 return Smi::FromInt(4); // 4 == "never". |
8312 } | 8288 } |
8313 if (FLAG_always_opt) { | 8289 if (FLAG_always_opt) { |
8314 return Smi::FromInt(3); // 3 == "always". | 8290 return Smi::FromInt(3); // 3 == "always". |
8315 } | 8291 } |
8316 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 8292 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
8317 return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes". | 8293 return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes". |
8318 : Smi::FromInt(2); // 2 == "no". | 8294 : Smi::FromInt(2); // 2 == "no". |
8319 } | 8295 } |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8472 argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv); | 8448 argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv); |
8473 } | 8449 } |
8474 | 8450 |
8475 for (int i = 0; i < argc; ++i) { | 8451 for (int i = 0; i < argc; ++i) { |
8476 MaybeObject* maybe = arguments->GetElement(offset + i); | 8452 MaybeObject* maybe = arguments->GetElement(offset + i); |
8477 Object* object; | 8453 Object* object; |
8478 if (!maybe->To<Object>(&object)) return maybe; | 8454 if (!maybe->To<Object>(&object)) return maybe; |
8479 argv[i] = Handle<Object>(object); | 8455 argv[i] = Handle<Object>(object); |
8480 } | 8456 } |
8481 | 8457 |
8482 bool threw = false; | 8458 bool threw; |
8483 Handle<JSReceiver> hfun(fun); | 8459 Handle<JSReceiver> hfun(fun); |
8484 Handle<Object> hreceiver(receiver); | 8460 Handle<Object> hreceiver(receiver); |
8485 Handle<Object> result = Execution::Call( | 8461 Handle<Object> result = Execution::Call( |
8486 hfun, hreceiver, argc, reinterpret_cast<Object***>(argv), &threw, true); | 8462 hfun, hreceiver, argc, reinterpret_cast<Object***>(argv), &threw, true); |
8487 | 8463 |
8488 if (threw) return Failure::Exception(); | 8464 if (threw) return Failure::Exception(); |
8489 return *result; | 8465 return *result; |
8490 } | 8466 } |
8491 | 8467 |
8492 | 8468 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8639 if (holder.is_null()) { | 8615 if (holder.is_null()) { |
8640 return isolate->heap()->true_value(); | 8616 return isolate->heap()->true_value(); |
8641 } | 8617 } |
8642 | 8618 |
8643 // If the slot was found in a context, it should be DONT_DELETE. | 8619 // If the slot was found in a context, it should be DONT_DELETE. |
8644 if (holder->IsContext()) { | 8620 if (holder->IsContext()) { |
8645 return isolate->heap()->false_value(); | 8621 return isolate->heap()->false_value(); |
8646 } | 8622 } |
8647 | 8623 |
8648 // The slot was found in a JSObject, either a context extension object, | 8624 // The slot was found in a JSObject, either a context extension object, |
8649 // the global object, or an arguments object. Try to delete it | 8625 // the global object, or the subject of a with. Try to delete it |
8650 // (respecting DONT_DELETE). For consistency with V8's usual behavior, | 8626 // (respecting DONT_DELETE). |
8651 // which allows deleting all parameters in functions that mention | |
8652 // 'arguments', we do this even for the case of slots found on an | |
8653 // arguments object. The slot was found on an arguments object if the | |
8654 // index is non-negative. | |
8655 Handle<JSObject> object = Handle<JSObject>::cast(holder); | 8627 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
8656 if (index >= 0) { | 8628 return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION); |
8657 return object->DeleteElement(index, JSReceiver::NORMAL_DELETION); | |
8658 } else { | |
8659 return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION); | |
8660 } | |
8661 } | 8629 } |
8662 | 8630 |
8663 | 8631 |
8664 // A mechanism to return a pair of Object pointers in registers (if possible). | 8632 // A mechanism to return a pair of Object pointers in registers (if possible). |
8665 // How this is achieved is calling convention-dependent. | 8633 // How this is achieved is calling convention-dependent. |
8666 // All currently supported x86 compiles uses calling conventions that are cdecl | 8634 // All currently supported x86 compiles uses calling conventions that are cdecl |
8667 // variants where a 64-bit value is returned in two 32-bit registers | 8635 // variants where a 64-bit value is returned in two 32-bit registers |
8668 // (edx:eax on ia32, r1:r0 on ARM). | 8636 // (edx:eax on ia32, r1:r0 on ARM). |
8669 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. | 8637 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. |
8670 // In Win64 calling convention, a struct of two pointers is returned in memory, | 8638 // In Win64 calling convention, a struct of two pointers is returned in memory, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8735 int index; | 8703 int index; |
8736 PropertyAttributes attributes; | 8704 PropertyAttributes attributes; |
8737 ContextLookupFlags flags = FOLLOW_CHAINS; | 8705 ContextLookupFlags flags = FOLLOW_CHAINS; |
8738 BindingFlags binding_flags; | 8706 BindingFlags binding_flags; |
8739 Handle<Object> holder = context->Lookup(name, | 8707 Handle<Object> holder = context->Lookup(name, |
8740 flags, | 8708 flags, |
8741 &index, | 8709 &index, |
8742 &attributes, | 8710 &attributes, |
8743 &binding_flags); | 8711 &binding_flags); |
8744 | 8712 |
8745 // If the index is non-negative, the slot has been found in a local | 8713 // If the index is non-negative, the slot has been found in a context. |
8746 // variable or a parameter. Read it from the context object or the | |
8747 // arguments object. | |
8748 if (index >= 0) { | 8714 if (index >= 0) { |
8749 // If the "property" we were looking for is a local variable or an | 8715 ASSERT(holder->IsContext()); |
8750 // argument in a context, the receiver is the global object; see | 8716 // If the "property" we were looking for is a local variable, the |
8751 // ECMA-262, 3rd., 10.1.6 and 10.2.3. | 8717 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3. |
8752 // | 8718 // |
8753 // Use the hole as the receiver to signal that the receiver is | 8719 // Use the hole as the receiver to signal that the receiver is implicit |
8754 // implicit and that the global receiver should be used. | 8720 // and that the global receiver should be used (as distinguished from an |
| 8721 // explicit receiver that happens to be a global object). |
8755 Handle<Object> receiver = isolate->factory()->the_hole_value(); | 8722 Handle<Object> receiver = isolate->factory()->the_hole_value(); |
8756 MaybeObject* value = (holder->IsContext()) | 8723 Object* value = Context::cast(*holder)->get(index); |
8757 ? Context::cast(*holder)->get(index) | |
8758 : JSObject::cast(*holder)->GetElement(index); | |
8759 // Check for uninitialized bindings. | 8724 // Check for uninitialized bindings. |
8760 if (holder->IsContext() && | 8725 if (binding_flags == MUTABLE_CHECK_INITIALIZED && value->IsTheHole()) { |
8761 binding_flags == MUTABLE_CHECK_INITIALIZED && | |
8762 value->IsTheHole()) { | |
8763 Handle<Object> reference_error = | 8726 Handle<Object> reference_error = |
8764 isolate->factory()->NewReferenceError("not_defined", | 8727 isolate->factory()->NewReferenceError("not_defined", |
8765 HandleVector(&name, 1)); | 8728 HandleVector(&name, 1)); |
8766 return MakePair(isolate->Throw(*reference_error), NULL); | 8729 return MakePair(isolate->Throw(*reference_error), NULL); |
8767 } else { | 8730 } else { |
8768 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); | 8731 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); |
8769 } | 8732 } |
8770 } | 8733 } |
8771 | 8734 |
8772 // If the holder is found, we read the property from it. | 8735 // Otherwise, if the slot was found the holder is a context extension |
8773 if (!holder.is_null() && holder->IsJSObject()) { | 8736 // object, subject of a with, or a global object. We read the named |
8774 ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name)); | 8737 // property from it. |
8775 JSObject* object = JSObject::cast(*holder); | 8738 if (!holder.is_null()) { |
8776 Object* receiver; | 8739 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
8777 if (object->IsGlobalObject()) { | 8740 ASSERT(object->HasProperty(*name)); |
8778 receiver = GlobalObject::cast(object)->global_receiver(); | 8741 // GetProperty below can cause GC. |
8779 } else if (context->is_exception_holder(*holder)) { | 8742 Handle<Object> receiver_handle(object->IsGlobalObject() |
8780 // Use the hole as the receiver to signal that the receiver is | 8743 ? GlobalObject::cast(*object)->global_receiver() |
8781 // implicit and that the global receiver should be used. | 8744 : ComputeReceiverForNonGlobal(isolate, *object)); |
8782 receiver = isolate->heap()->the_hole_value(); | |
8783 } else { | |
8784 receiver = ComputeReceiverForNonGlobal(isolate, object); | |
8785 } | |
8786 | 8745 |
8787 // GetProperty below can cause GC. | 8746 // No need to unhole the value here. This is taken care of by the |
8788 Handle<Object> receiver_handle(receiver); | |
8789 | |
8790 // No need to unhole the value here. This is taken care of by the | |
8791 // GetProperty function. | 8747 // GetProperty function. |
8792 MaybeObject* value = object->GetProperty(*name); | 8748 MaybeObject* value = object->GetProperty(*name); |
8793 return MakePair(value, *receiver_handle); | 8749 return MakePair(value, *receiver_handle); |
8794 } | 8750 } |
8795 | 8751 |
8796 if (throw_error) { | 8752 if (throw_error) { |
8797 // The property doesn't exist - throw exception. | 8753 // The property doesn't exist - throw exception. |
8798 Handle<Object> reference_error = | 8754 Handle<Object> reference_error = |
8799 isolate->factory()->NewReferenceError("not_defined", | 8755 isolate->factory()->NewReferenceError("not_defined", |
8800 HandleVector(&name, 1)); | 8756 HandleVector(&name, 1)); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8833 PropertyAttributes attributes; | 8789 PropertyAttributes attributes; |
8834 ContextLookupFlags flags = FOLLOW_CHAINS; | 8790 ContextLookupFlags flags = FOLLOW_CHAINS; |
8835 BindingFlags binding_flags; | 8791 BindingFlags binding_flags; |
8836 Handle<Object> holder = context->Lookup(name, | 8792 Handle<Object> holder = context->Lookup(name, |
8837 flags, | 8793 flags, |
8838 &index, | 8794 &index, |
8839 &attributes, | 8795 &attributes, |
8840 &binding_flags); | 8796 &binding_flags); |
8841 | 8797 |
8842 if (index >= 0) { | 8798 if (index >= 0) { |
8843 if (holder->IsContext()) { | 8799 // The property was found in a context slot. |
8844 Handle<Context> context = Handle<Context>::cast(holder); | 8800 Handle<Context> context = Handle<Context>::cast(holder); |
8845 if (binding_flags == MUTABLE_CHECK_INITIALIZED && | 8801 if (binding_flags == MUTABLE_CHECK_INITIALIZED && |
8846 context->get(index)->IsTheHole()) { | 8802 context->get(index)->IsTheHole()) { |
8847 Handle<Object> error = | 8803 Handle<Object> error = |
8848 isolate->factory()->NewReferenceError("not_defined", | 8804 isolate->factory()->NewReferenceError("not_defined", |
8849 HandleVector(&name, 1)); | 8805 HandleVector(&name, 1)); |
8850 return isolate->Throw(*error); | 8806 return isolate->Throw(*error); |
8851 } | 8807 } |
8852 // Ignore if read_only variable. | 8808 // Ignore if read_only variable. |
8853 if ((attributes & READ_ONLY) == 0) { | 8809 if ((attributes & READ_ONLY) == 0) { |
8854 // Context is a fixed array and set cannot fail. | 8810 // Context is a fixed array and set cannot fail. |
8855 context->set(index, *value); | 8811 context->set(index, *value); |
8856 } else if (strict_mode == kStrictMode) { | 8812 } else if (strict_mode == kStrictMode) { |
8857 // Setting read only property in strict mode. | 8813 // Setting read only property in strict mode. |
8858 Handle<Object> error = | 8814 Handle<Object> error = |
8859 isolate->factory()->NewTypeError("strict_cannot_assign", | 8815 isolate->factory()->NewTypeError("strict_cannot_assign", |
8860 HandleVector(&name, 1)); | 8816 HandleVector(&name, 1)); |
8861 return isolate->Throw(*error); | 8817 return isolate->Throw(*error); |
8862 } | |
8863 } else { | |
8864 ASSERT((attributes & READ_ONLY) == 0); | |
8865 Handle<Object> result = | |
8866 SetElement(Handle<JSObject>::cast(holder), index, value, strict_mode); | |
8867 if (result.is_null()) { | |
8868 ASSERT(isolate->has_pending_exception()); | |
8869 return Failure::Exception(); | |
8870 } | |
8871 } | 8818 } |
8872 return *value; | 8819 return *value; |
8873 } | 8820 } |
8874 | 8821 |
8875 // Slow case: The property is not in a FixedArray context. | 8822 // Slow case: The property is not in a context slot. It is either in a |
8876 // It is either in an JSObject extension context or it was not found. | 8823 // context extension object, a property of the subject of a with, or a |
8877 Handle<JSObject> context_ext; | 8824 // property of the global object. |
| 8825 Handle<JSObject> object; |
8878 | 8826 |
8879 if (!holder.is_null()) { | 8827 if (!holder.is_null()) { |
8880 // The property exists in the extension context. | 8828 // The property exists on the holder. |
8881 context_ext = Handle<JSObject>::cast(holder); | 8829 object = Handle<JSObject>::cast(holder); |
8882 } else { | 8830 } else { |
8883 // The property was not found. | 8831 // The property was not found. |
8884 ASSERT(attributes == ABSENT); | 8832 ASSERT(attributes == ABSENT); |
8885 | 8833 |
8886 if (strict_mode == kStrictMode) { | 8834 if (strict_mode == kStrictMode) { |
8887 // Throw in strict mode (assignment to undefined variable). | 8835 // Throw in strict mode (assignment to undefined variable). |
8888 Handle<Object> error = | 8836 Handle<Object> error = |
8889 isolate->factory()->NewReferenceError( | 8837 isolate->factory()->NewReferenceError( |
8890 "not_defined", HandleVector(&name, 1)); | 8838 "not_defined", HandleVector(&name, 1)); |
8891 return isolate->Throw(*error); | 8839 return isolate->Throw(*error); |
8892 } | 8840 } |
8893 // In non-strict mode, the property is stored in the global context. | 8841 // In non-strict mode, the property is added to the global object. |
8894 attributes = NONE; | 8842 attributes = NONE; |
8895 context_ext = Handle<JSObject>(isolate->context()->global()); | 8843 object = Handle<JSObject>(isolate->context()->global()); |
8896 } | 8844 } |
8897 | 8845 |
8898 // Set the property, but ignore if read_only variable on the context | 8846 // Set the property if it's not read only or doesn't yet exist. |
8899 // extension object itself. | |
8900 if ((attributes & READ_ONLY) == 0 || | 8847 if ((attributes & READ_ONLY) == 0 || |
8901 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { | 8848 (object->GetLocalPropertyAttribute(*name) == ABSENT)) { |
8902 RETURN_IF_EMPTY_HANDLE( | 8849 RETURN_IF_EMPTY_HANDLE( |
8903 isolate, | 8850 isolate, |
8904 SetProperty(context_ext, name, value, NONE, strict_mode)); | 8851 SetProperty(object, name, value, NONE, strict_mode)); |
8905 } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) { | 8852 } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) { |
8906 // Setting read only property in strict mode. | 8853 // Setting read only property in strict mode. |
8907 Handle<Object> error = | 8854 Handle<Object> error = |
8908 isolate->factory()->NewTypeError( | 8855 isolate->factory()->NewTypeError( |
8909 "strict_cannot_assign", HandleVector(&name, 1)); | 8856 "strict_cannot_assign", HandleVector(&name, 1)); |
8910 return isolate->Throw(*error); | 8857 return isolate->Throw(*error); |
8911 } | 8858 } |
8912 return *value; | 8859 return *value; |
8913 } | 8860 } |
8914 | 8861 |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9114 | 9061 |
9115 | 9062 |
9116 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) { | 9063 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) { |
9117 HandleScope scope(isolate); | 9064 HandleScope scope(isolate); |
9118 ASSERT(args.length() == 2); | 9065 ASSERT(args.length() == 2); |
9119 | 9066 |
9120 CONVERT_ARG_CHECKED(String, str, 0); | 9067 CONVERT_ARG_CHECKED(String, str, 0); |
9121 FlattenString(str); | 9068 FlattenString(str); |
9122 | 9069 |
9123 CONVERT_ARG_CHECKED(JSArray, output, 1); | 9070 CONVERT_ARG_CHECKED(JSArray, output, 1); |
| 9071 |
| 9072 MaybeObject* maybe_result_array = |
| 9073 output->EnsureCanContainNonSmiElements(); |
| 9074 if (maybe_result_array->IsFailure()) return maybe_result_array; |
9124 RUNTIME_ASSERT(output->HasFastElements()); | 9075 RUNTIME_ASSERT(output->HasFastElements()); |
9125 | 9076 |
9126 AssertNoAllocation no_allocation; | 9077 AssertNoAllocation no_allocation; |
9127 | 9078 |
9128 FixedArray* output_array = FixedArray::cast(output->elements()); | 9079 FixedArray* output_array = FixedArray::cast(output->elements()); |
9129 RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE); | 9080 RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE); |
9130 bool result; | 9081 bool result; |
9131 String::FlatContent str_content = str->GetFlatContent(); | 9082 String::FlatContent str_content = str->GetFlatContent(); |
9132 if (str_content.IsAscii()) { | 9083 if (str_content.IsAscii()) { |
9133 result = DateParser::Parse(str_content.ToAsciiVector(), | 9084 result = DateParser::Parse(str_content.ToAsciiVector(), |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9299 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 9250 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
9300 ASSERT(Context::cast(frame->context()) == *context); | 9251 ASSERT(Context::cast(frame->context()) == *context); |
9301 #endif | 9252 #endif |
9302 | 9253 |
9303 // Find where the 'eval' symbol is bound. It is unaliased only if | 9254 // Find where the 'eval' symbol is bound. It is unaliased only if |
9304 // it is bound in the global context. | 9255 // it is bound in the global context. |
9305 int index = -1; | 9256 int index = -1; |
9306 PropertyAttributes attributes = ABSENT; | 9257 PropertyAttributes attributes = ABSENT; |
9307 BindingFlags binding_flags; | 9258 BindingFlags binding_flags; |
9308 while (true) { | 9259 while (true) { |
| 9260 // Don't follow context chains in Context::Lookup and implement the loop |
| 9261 // up the context chain here, so that we can know the context where eval |
| 9262 // was found. |
9309 receiver = context->Lookup(isolate->factory()->eval_symbol(), | 9263 receiver = context->Lookup(isolate->factory()->eval_symbol(), |
9310 FOLLOW_PROTOTYPE_CHAIN, | 9264 FOLLOW_PROTOTYPE_CHAIN, |
9311 &index, | 9265 &index, |
9312 &attributes, | 9266 &attributes, |
9313 &binding_flags); | 9267 &binding_flags); |
9314 // Stop search when eval is found or when the global context is | 9268 // Stop search when eval is found or when the global context is |
9315 // reached. | 9269 // reached. |
9316 if (attributes != ABSENT || context->IsGlobalContext()) break; | 9270 if (attributes != ABSENT || context->IsGlobalContext()) break; |
9317 context = Handle<Context>(context->previous(), isolate); | 9271 context = Handle<Context>(context->previous(), isolate); |
9318 } | 9272 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9414 } | 9368 } |
9415 | 9369 |
9416 | 9370 |
9417 // Push an object unto an array of objects if it is not already in the | 9371 // Push an object unto an array of objects if it is not already in the |
9418 // array. Returns true if the element was pushed on the stack and | 9372 // array. Returns true if the element was pushed on the stack and |
9419 // false otherwise. | 9373 // false otherwise. |
9420 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) { | 9374 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) { |
9421 ASSERT(args.length() == 2); | 9375 ASSERT(args.length() == 2); |
9422 CONVERT_CHECKED(JSArray, array, args[0]); | 9376 CONVERT_CHECKED(JSArray, array, args[0]); |
9423 CONVERT_CHECKED(JSObject, element, args[1]); | 9377 CONVERT_CHECKED(JSObject, element, args[1]); |
9424 RUNTIME_ASSERT(array->HasFastElements()); | 9378 RUNTIME_ASSERT(array->HasFastElements() || array->HasFastSmiOnlyElements()); |
9425 int length = Smi::cast(array->length())->value(); | 9379 int length = Smi::cast(array->length())->value(); |
9426 FixedArray* elements = FixedArray::cast(array->elements()); | 9380 FixedArray* elements = FixedArray::cast(array->elements()); |
9427 for (int i = 0; i < length; i++) { | 9381 for (int i = 0; i < length; i++) { |
9428 if (elements->get(i) == element) return isolate->heap()->false_value(); | 9382 if (elements->get(i) == element) return isolate->heap()->false_value(); |
9429 } | 9383 } |
9430 Object* obj; | 9384 Object* obj; |
9431 // Strict not needed. Used for cycle detection in Array join implementation. | 9385 // Strict not needed. Used for cycle detection in Array join implementation. |
9432 { MaybeObject* maybe_obj = | 9386 { MaybeObject* maybe_obj = |
9433 array->SetFastElement(length, element, kNonStrictMode, true); | 9387 array->SetFastElement(length, element, kNonStrictMode, true); |
9434 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9388 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9497 index_offset_ += delta; | 9451 index_offset_ += delta; |
9498 } | 9452 } |
9499 } | 9453 } |
9500 | 9454 |
9501 Handle<JSArray> ToArray() { | 9455 Handle<JSArray> ToArray() { |
9502 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); | 9456 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); |
9503 Handle<Object> length = | 9457 Handle<Object> length = |
9504 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); | 9458 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); |
9505 Handle<Map> map; | 9459 Handle<Map> map; |
9506 if (fast_elements_) { | 9460 if (fast_elements_) { |
9507 map = isolate_->factory()->GetFastElementsMap(Handle<Map>(array->map())); | 9461 map = isolate_->factory()->GetElementsTransitionMap(array, |
| 9462 FAST_ELEMENTS); |
9508 } else { | 9463 } else { |
9509 map = isolate_->factory()->GetSlowElementsMap(Handle<Map>(array->map())); | 9464 map = isolate_->factory()->GetElementsTransitionMap(array, |
| 9465 DICTIONARY_ELEMENTS); |
9510 } | 9466 } |
9511 array->set_map(*map); | 9467 array->set_map(*map); |
9512 array->set_length(*length); | 9468 array->set_length(*length); |
9513 array->set_elements(*storage_); | 9469 array->set_elements(*storage_); |
9514 return array; | 9470 return array; |
9515 } | 9471 } |
9516 | 9472 |
9517 private: | 9473 private: |
9518 // Convert storage to dictionary mode. | 9474 // Convert storage to dictionary mode. |
9519 void SetDictionaryMode(uint32_t index) { | 9475 void SetDictionaryMode(uint32_t index) { |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9643 uint32_t b = *bp; | 9599 uint32_t b = *bp; |
9644 return (a == b) ? 0 : (a < b) ? -1 : 1; | 9600 return (a == b) ? 0 : (a < b) ? -1 : 1; |
9645 } | 9601 } |
9646 | 9602 |
9647 | 9603 |
9648 static void CollectElementIndices(Handle<JSObject> object, | 9604 static void CollectElementIndices(Handle<JSObject> object, |
9649 uint32_t range, | 9605 uint32_t range, |
9650 List<uint32_t>* indices) { | 9606 List<uint32_t>* indices) { |
9651 ElementsKind kind = object->GetElementsKind(); | 9607 ElementsKind kind = object->GetElementsKind(); |
9652 switch (kind) { | 9608 switch (kind) { |
| 9609 case FAST_SMI_ONLY_ELEMENTS: |
9653 case FAST_ELEMENTS: { | 9610 case FAST_ELEMENTS: { |
9654 Handle<FixedArray> elements(FixedArray::cast(object->elements())); | 9611 Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
9655 uint32_t length = static_cast<uint32_t>(elements->length()); | 9612 uint32_t length = static_cast<uint32_t>(elements->length()); |
9656 if (range < length) length = range; | 9613 if (range < length) length = range; |
9657 for (uint32_t i = 0; i < length; i++) { | 9614 for (uint32_t i = 0; i < length; i++) { |
9658 if (!elements->get(i)->IsTheHole()) { | 9615 if (!elements->get(i)->IsTheHole()) { |
9659 indices->Add(i); | 9616 indices->Add(i); |
9660 } | 9617 } |
9661 } | 9618 } |
9662 break; | 9619 break; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9762 * with the element index and the element's value. | 9719 * with the element index and the element's value. |
9763 * Afterwards it increments the base-index of the visitor by the array | 9720 * Afterwards it increments the base-index of the visitor by the array |
9764 * length. | 9721 * length. |
9765 * Returns false if any access threw an exception, otherwise true. | 9722 * Returns false if any access threw an exception, otherwise true. |
9766 */ | 9723 */ |
9767 static bool IterateElements(Isolate* isolate, | 9724 static bool IterateElements(Isolate* isolate, |
9768 Handle<JSArray> receiver, | 9725 Handle<JSArray> receiver, |
9769 ArrayConcatVisitor* visitor) { | 9726 ArrayConcatVisitor* visitor) { |
9770 uint32_t length = static_cast<uint32_t>(receiver->length()->Number()); | 9727 uint32_t length = static_cast<uint32_t>(receiver->length()->Number()); |
9771 switch (receiver->GetElementsKind()) { | 9728 switch (receiver->GetElementsKind()) { |
| 9729 case FAST_SMI_ONLY_ELEMENTS: |
9772 case FAST_ELEMENTS: { | 9730 case FAST_ELEMENTS: { |
9773 // Run through the elements FixedArray and use HasElement and GetElement | 9731 // Run through the elements FixedArray and use HasElement and GetElement |
9774 // to check the prototype for missing elements. | 9732 // to check the prototype for missing elements. |
9775 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); | 9733 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); |
9776 int fast_length = static_cast<int>(length); | 9734 int fast_length = static_cast<int>(length); |
9777 ASSERT(fast_length <= elements->length()); | 9735 ASSERT(fast_length <= elements->length()); |
9778 for (int j = 0; j < fast_length; j++) { | 9736 for (int j = 0; j < fast_length; j++) { |
9779 HandleScope loop_scope(isolate); | 9737 HandleScope loop_scope(isolate); |
9780 Handle<Object> element_value(elements->get(j), isolate); | 9738 Handle<Object> element_value(elements->get(j), isolate); |
9781 if (!element_value->IsTheHole()) { | 9739 if (!element_value->IsTheHole()) { |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9990 } | 9948 } |
9991 | 9949 |
9992 | 9950 |
9993 // Move contents of argument 0 (an array) to argument 1 (an array) | 9951 // Move contents of argument 0 (an array) to argument 1 (an array) |
9994 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) { | 9952 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) { |
9995 ASSERT(args.length() == 2); | 9953 ASSERT(args.length() == 2); |
9996 CONVERT_CHECKED(JSArray, from, args[0]); | 9954 CONVERT_CHECKED(JSArray, from, args[0]); |
9997 CONVERT_CHECKED(JSArray, to, args[1]); | 9955 CONVERT_CHECKED(JSArray, to, args[1]); |
9998 FixedArrayBase* new_elements = from->elements(); | 9956 FixedArrayBase* new_elements = from->elements(); |
9999 MaybeObject* maybe_new_map; | 9957 MaybeObject* maybe_new_map; |
| 9958 ElementsKind elements_kind; |
10000 if (new_elements->map() == isolate->heap()->fixed_array_map() || | 9959 if (new_elements->map() == isolate->heap()->fixed_array_map() || |
10001 new_elements->map() == isolate->heap()->fixed_cow_array_map()) { | 9960 new_elements->map() == isolate->heap()->fixed_cow_array_map()) { |
10002 maybe_new_map = to->map()->GetFastElementsMap(); | 9961 elements_kind = FAST_ELEMENTS; |
10003 } else if (new_elements->map() == | 9962 } else if (new_elements->map() == |
10004 isolate->heap()->fixed_double_array_map()) { | 9963 isolate->heap()->fixed_double_array_map()) { |
10005 maybe_new_map = to->map()->GetFastDoubleElementsMap(); | 9964 elements_kind = FAST_DOUBLE_ELEMENTS; |
10006 } else { | 9965 } else { |
10007 maybe_new_map = to->map()->GetSlowElementsMap(); | 9966 elements_kind = DICTIONARY_ELEMENTS; |
10008 } | 9967 } |
| 9968 maybe_new_map = to->GetElementsTransitionMap(elements_kind); |
10009 Object* new_map; | 9969 Object* new_map; |
10010 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 9970 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
10011 to->set_map(Map::cast(new_map)); | 9971 to->set_map(Map::cast(new_map)); |
10012 to->set_elements(new_elements); | 9972 to->set_elements(new_elements); |
10013 to->set_length(from->length()); | 9973 to->set_length(from->length()); |
10014 Object* obj; | 9974 Object* obj; |
10015 { MaybeObject* maybe_obj = from->ResetElements(); | 9975 { MaybeObject* maybe_obj = from->ResetElements(); |
10016 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9976 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
10017 } | 9977 } |
10018 from->set_length(Smi::FromInt(0)); | 9978 from->set_length(Smi::FromInt(0)); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10083 for (int i = 0; i < keys_length; i++) { | 10043 for (int i = 0; i < keys_length; i++) { |
10084 Object* key = keys->get(i); | 10044 Object* key = keys->get(i); |
10085 uint32_t index = 0; | 10045 uint32_t index = 0; |
10086 if (!key->ToArrayIndex(&index) || index >= length) { | 10046 if (!key->ToArrayIndex(&index) || index >= length) { |
10087 // Zap invalid keys. | 10047 // Zap invalid keys. |
10088 keys->set_undefined(i); | 10048 keys->set_undefined(i); |
10089 } | 10049 } |
10090 } | 10050 } |
10091 return *isolate->factory()->NewJSArrayWithElements(keys); | 10051 return *isolate->factory()->NewJSArrayWithElements(keys); |
10092 } else { | 10052 } else { |
10093 ASSERT(array->HasFastElements() || array->HasFastDoubleElements()); | 10053 ASSERT(array->HasFastElements() || |
| 10054 array->HasFastSmiOnlyElements() || |
| 10055 array->HasFastDoubleElements()); |
10094 Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); | 10056 Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); |
10095 // -1 means start of array. | 10057 // -1 means start of array. |
10096 single_interval->set(0, Smi::FromInt(-1)); | 10058 single_interval->set(0, Smi::FromInt(-1)); |
10097 FixedArrayBase* elements = FixedArrayBase::cast(array->elements()); | 10059 FixedArrayBase* elements = FixedArrayBase::cast(array->elements()); |
10098 uint32_t actual_length = | 10060 uint32_t actual_length = |
10099 static_cast<uint32_t>(elements->length()); | 10061 static_cast<uint32_t>(elements->length()); |
10100 uint32_t min_length = actual_length < length ? actual_length : length; | 10062 uint32_t min_length = actual_length < length ? actual_length : length; |
10101 Handle<Object> length_object = | 10063 Handle<Object> length_object = |
10102 isolate->factory()->NewNumber(static_cast<double>(min_length)); | 10064 isolate->factory()->NewNumber(static_cast<double>(min_length)); |
10103 single_interval->set(1, *length_object); | 10065 single_interval->set(1, *length_object); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10202 result->holder())->FastPropertyAt(result->GetFieldIndex()); | 10164 result->holder())->FastPropertyAt(result->GetFieldIndex()); |
10203 if (value->IsTheHole()) { | 10165 if (value->IsTheHole()) { |
10204 return heap->undefined_value(); | 10166 return heap->undefined_value(); |
10205 } | 10167 } |
10206 return value; | 10168 return value; |
10207 case CONSTANT_FUNCTION: | 10169 case CONSTANT_FUNCTION: |
10208 return result->GetConstantFunction(); | 10170 return result->GetConstantFunction(); |
10209 case CALLBACKS: { | 10171 case CALLBACKS: { |
10210 Object* structure = result->GetCallbackObject(); | 10172 Object* structure = result->GetCallbackObject(); |
10211 if (structure->IsForeign() || structure->IsAccessorInfo()) { | 10173 if (structure->IsForeign() || structure->IsAccessorInfo()) { |
10212 MaybeObject* maybe_value = receiver->GetPropertyWithCallback( | 10174 MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback( |
10213 receiver, structure, name, result->holder()); | 10175 receiver, structure, name); |
10214 if (!maybe_value->ToObject(&value)) { | 10176 if (!maybe_value->ToObject(&value)) { |
10215 if (maybe_value->IsRetryAfterGC()) return maybe_value; | 10177 if (maybe_value->IsRetryAfterGC()) return maybe_value; |
10216 ASSERT(maybe_value->IsException()); | 10178 ASSERT(maybe_value->IsException()); |
10217 maybe_value = heap->isolate()->pending_exception(); | 10179 maybe_value = heap->isolate()->pending_exception(); |
10218 heap->isolate()->clear_pending_exception(); | 10180 heap->isolate()->clear_pending_exception(); |
10219 if (caught_exception != NULL) { | 10181 if (caught_exception != NULL) { |
10220 *caught_exception = true; | 10182 *caught_exception = true; |
10221 } | 10183 } |
10222 return maybe_value; | 10184 return maybe_value; |
10223 } | 10185 } |
(...skipping 1229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11453 // NOTE: This might require several heap iterations. If the SharedFunctionInfo | 11415 // NOTE: This might require several heap iterations. If the SharedFunctionInfo |
11454 // which is found is not compiled it is compiled and the heap is iterated | 11416 // which is found is not compiled it is compiled and the heap is iterated |
11455 // again as the compilation might create inner functions from the newly | 11417 // again as the compilation might create inner functions from the newly |
11456 // compiled function and the actual requested break point might be in one of | 11418 // compiled function and the actual requested break point might be in one of |
11457 // these functions. | 11419 // these functions. |
11458 bool done = false; | 11420 bool done = false; |
11459 // The current candidate for the source position: | 11421 // The current candidate for the source position: |
11460 int target_start_position = RelocInfo::kNoPosition; | 11422 int target_start_position = RelocInfo::kNoPosition; |
11461 Handle<SharedFunctionInfo> target; | 11423 Handle<SharedFunctionInfo> target; |
11462 while (!done) { | 11424 while (!done) { |
11463 HeapIterator iterator; | 11425 { // Extra scope for iterator and no-allocation. |
11464 for (HeapObject* obj = iterator.next(); | 11426 isolate->heap()->EnsureHeapIsIterable(); |
11465 obj != NULL; obj = iterator.next()) { | 11427 AssertNoAllocation no_alloc_during_heap_iteration; |
11466 if (obj->IsSharedFunctionInfo()) { | 11428 HeapIterator iterator; |
11467 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj)); | 11429 for (HeapObject* obj = iterator.next(); |
11468 if (shared->script() == *script) { | 11430 obj != NULL; obj = iterator.next()) { |
11469 // If the SharedFunctionInfo found has the requested script data and | 11431 if (obj->IsSharedFunctionInfo()) { |
11470 // contains the source position it is a candidate. | 11432 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj)); |
11471 int start_position = shared->function_token_position(); | 11433 if (shared->script() == *script) { |
11472 if (start_position == RelocInfo::kNoPosition) { | 11434 // If the SharedFunctionInfo found has the requested script data and |
11473 start_position = shared->start_position(); | 11435 // contains the source position it is a candidate. |
11474 } | 11436 int start_position = shared->function_token_position(); |
11475 if (start_position <= position && | 11437 if (start_position == RelocInfo::kNoPosition) { |
11476 position <= shared->end_position()) { | 11438 start_position = shared->start_position(); |
11477 // If there is no candidate or this function is within the current | 11439 } |
11478 // candidate this is the new candidate. | 11440 if (start_position <= position && |
11479 if (target.is_null()) { | 11441 position <= shared->end_position()) { |
11480 target_start_position = start_position; | 11442 // If there is no candidate or this function is within the current |
11481 target = shared; | 11443 // candidate this is the new candidate. |
11482 } else { | 11444 if (target.is_null()) { |
11483 if (target_start_position == start_position && | 11445 target_start_position = start_position; |
11484 shared->end_position() == target->end_position()) { | 11446 target = shared; |
11485 // If a top-level function contain only one function | 11447 } else { |
11486 // declartion the source for the top-level and the function is | 11448 if (target_start_position == start_position && |
11487 // the same. In that case prefer the non top-level function. | 11449 shared->end_position() == target->end_position()) { |
11488 if (!shared->is_toplevel()) { | 11450 // If a top-level function contain only one function |
| 11451 // declartion the source for the top-level and the |
| 11452 // function is the same. In that case prefer the non |
| 11453 // top-level function. |
| 11454 if (!shared->is_toplevel()) { |
| 11455 target_start_position = start_position; |
| 11456 target = shared; |
| 11457 } |
| 11458 } else if (target_start_position <= start_position && |
| 11459 shared->end_position() <= target->end_position()) { |
| 11460 // This containment check includes equality as a function |
| 11461 // inside a top-level function can share either start or end |
| 11462 // position with the top-level function. |
11489 target_start_position = start_position; | 11463 target_start_position = start_position; |
11490 target = shared; | 11464 target = shared; |
11491 } | 11465 } |
11492 } else if (target_start_position <= start_position && | |
11493 shared->end_position() <= target->end_position()) { | |
11494 // This containment check includes equality as a function inside | |
11495 // a top-level function can share either start or end position | |
11496 // with the top-level function. | |
11497 target_start_position = start_position; | |
11498 target = shared; | |
11499 } | 11466 } |
11500 } | 11467 } |
11501 } | 11468 } |
11502 } | 11469 } |
11503 } | 11470 } // End for loop. |
11504 } | 11471 } // End No allocation scope. |
11505 | 11472 |
11506 if (target.is_null()) { | 11473 if (target.is_null()) { |
11507 return isolate->heap()->undefined_value(); | 11474 return isolate->heap()->undefined_value(); |
11508 } | 11475 } |
11509 | 11476 |
11510 // If the candidate found is compiled we are done. NOTE: when lazy | 11477 // If the candidate found is compiled we are done. NOTE: when lazy |
11511 // compilation of inner functions is introduced some additional checking | 11478 // compilation of inner functions is introduced some additional checking |
11512 // needs to be done here to compile inner functions. | 11479 // needs to be done here to compile inner functions. |
11513 done = target->is_compiled(); | 11480 done = target->is_compiled(); |
11514 if (!done) { | 11481 if (!done) { |
11515 // If the candidate is not compiled compile it to reveal any inner | 11482 // If the candidate is not compiled compile it to reveal any inner |
11516 // functions which might contain the requested source position. | 11483 // functions which might contain the requested source position. |
11517 CompileLazyShared(target, KEEP_EXCEPTION); | 11484 CompileLazyShared(target, KEEP_EXCEPTION); |
11518 } | 11485 } |
11519 } | 11486 } // End while loop. |
11520 | 11487 |
11521 return *target; | 11488 return *target; |
11522 } | 11489 } |
11523 | 11490 |
11524 | 11491 |
11525 // Changes the state of a break point in a script and returns source position | 11492 // Changes the state of a break point in a script and returns source position |
11526 // where break point was set. NOTE: Regarding performance see the NOTE for | 11493 // where break point was set. NOTE: Regarding performance see the NOTE for |
11527 // GetScriptFromScriptData. | 11494 // GetScriptFromScriptData. |
11528 // args[0]: script to set break point in | 11495 // args[0]: script to set break point in |
11529 // args[1]: number: break source position (within the script source) | 11496 // args[1]: number: break source position (within the script source) |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11959 Handle<JSFunction>( | 11926 Handle<JSFunction>( |
11960 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, | 11927 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, |
11961 context)); | 11928 context)); |
11962 | 11929 |
11963 // Invoke the result of the compilation to get the evaluation function. | 11930 // Invoke the result of the compilation to get the evaluation function. |
11964 bool has_pending_exception; | 11931 bool has_pending_exception; |
11965 Handle<Object> receiver = isolate->global(); | 11932 Handle<Object> receiver = isolate->global(); |
11966 Handle<Object> result = | 11933 Handle<Object> result = |
11967 Execution::Call(compiled_function, receiver, 0, NULL, | 11934 Execution::Call(compiled_function, receiver, 0, NULL, |
11968 &has_pending_exception); | 11935 &has_pending_exception); |
| 11936 // Clear the oneshot breakpoints so that the debugger does not step further. |
| 11937 isolate->debug()->ClearStepping(); |
11969 if (has_pending_exception) return Failure::Exception(); | 11938 if (has_pending_exception) return Failure::Exception(); |
11970 return *result; | 11939 return *result; |
11971 } | 11940 } |
11972 | 11941 |
11973 | 11942 |
11974 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) { | 11943 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) { |
11975 HandleScope scope(isolate); | 11944 HandleScope scope(isolate); |
11976 ASSERT(args.length() == 0); | 11945 ASSERT(args.length() == 0); |
11977 | 11946 |
11978 // Fill the script objects. | 11947 // Fill the script objects. |
11979 Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts(); | 11948 Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts(); |
11980 | 11949 |
11981 // Convert the script objects to proper JS objects. | 11950 // Convert the script objects to proper JS objects. |
11982 for (int i = 0; i < instances->length(); i++) { | 11951 for (int i = 0; i < instances->length(); i++) { |
11983 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i))); | 11952 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i))); |
11984 // Get the script wrapper in a local handle before calling GetScriptWrapper, | 11953 // Get the script wrapper in a local handle before calling GetScriptWrapper, |
11985 // because using | 11954 // because using |
11986 // instances->set(i, *GetScriptWrapper(script)) | 11955 // instances->set(i, *GetScriptWrapper(script)) |
11987 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might | 11956 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might |
11988 // already have deferenced the instances handle. | 11957 // already have deferenced the instances handle. |
11989 Handle<JSValue> wrapper = GetScriptWrapper(script); | 11958 Handle<JSValue> wrapper = GetScriptWrapper(script); |
11990 instances->set(i, *wrapper); | 11959 instances->set(i, *wrapper); |
11991 } | 11960 } |
11992 | 11961 |
11993 // Return result as a JS array. | 11962 // Return result as a JS array. |
11994 Handle<JSObject> result = | 11963 Handle<JSObject> result = |
11995 isolate->factory()->NewJSObject(isolate->array_function()); | 11964 isolate->factory()->NewJSObject(isolate->array_function()); |
11996 Handle<JSArray>::cast(result)->SetContent(*instances); | 11965 isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances); |
11997 return *result; | 11966 return *result; |
11998 } | 11967 } |
11999 | 11968 |
12000 | 11969 |
12001 // Helper function used by Runtime_DebugReferencedBy below. | 11970 // Helper function used by Runtime_DebugReferencedBy below. |
12002 static int DebugReferencedBy(JSObject* target, | 11971 static int DebugReferencedBy(HeapIterator* iterator, |
| 11972 JSObject* target, |
12003 Object* instance_filter, int max_references, | 11973 Object* instance_filter, int max_references, |
12004 FixedArray* instances, int instances_size, | 11974 FixedArray* instances, int instances_size, |
12005 JSFunction* arguments_function) { | 11975 JSFunction* arguments_function) { |
12006 NoHandleAllocation ha; | 11976 NoHandleAllocation ha; |
12007 AssertNoAllocation no_alloc; | 11977 AssertNoAllocation no_alloc; |
12008 | 11978 |
12009 // Iterate the heap. | 11979 // Iterate the heap. |
12010 int count = 0; | 11980 int count = 0; |
12011 JSObject* last = NULL; | 11981 JSObject* last = NULL; |
12012 HeapIterator iterator; | |
12013 HeapObject* heap_obj = NULL; | 11982 HeapObject* heap_obj = NULL; |
12014 while (((heap_obj = iterator.next()) != NULL) && | 11983 while (((heap_obj = iterator->next()) != NULL) && |
12015 (max_references == 0 || count < max_references)) { | 11984 (max_references == 0 || count < max_references)) { |
12016 // Only look at all JSObjects. | 11985 // Only look at all JSObjects. |
12017 if (heap_obj->IsJSObject()) { | 11986 if (heap_obj->IsJSObject()) { |
12018 // Skip context extension objects and argument arrays as these are | 11987 // Skip context extension objects and argument arrays as these are |
12019 // checked in the context of functions using them. | 11988 // checked in the context of functions using them. |
12020 JSObject* obj = JSObject::cast(heap_obj); | 11989 JSObject* obj = JSObject::cast(heap_obj); |
12021 if (obj->IsJSContextExtensionObject() || | 11990 if (obj->IsJSContextExtensionObject() || |
12022 obj->map()->constructor() == arguments_function) { | 11991 obj->map()->constructor() == arguments_function) { |
12023 continue; | 11992 continue; |
12024 } | 11993 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12069 | 12038 |
12070 | 12039 |
12071 // Scan the heap for objects with direct references to an object | 12040 // Scan the heap for objects with direct references to an object |
12072 // args[0]: the object to find references to | 12041 // args[0]: the object to find references to |
12073 // args[1]: constructor function for instances to exclude (Mirror) | 12042 // args[1]: constructor function for instances to exclude (Mirror) |
12074 // args[2]: the the maximum number of objects to return | 12043 // args[2]: the the maximum number of objects to return |
12075 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) { | 12044 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) { |
12076 ASSERT(args.length() == 3); | 12045 ASSERT(args.length() == 3); |
12077 | 12046 |
12078 // First perform a full GC in order to avoid references from dead objects. | 12047 // First perform a full GC in order to avoid references from dead objects. |
12079 isolate->heap()->CollectAllGarbage(false); | 12048 isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
| 12049 // The heap iterator reserves the right to do a GC to make the heap iterable. |
| 12050 // Due to the GC above we know it won't need to do that, but it seems cleaner |
| 12051 // to get the heap iterator constructed before we start having unprotected |
| 12052 // Object* locals that are not protected by handles. |
12080 | 12053 |
12081 // Check parameters. | 12054 // Check parameters. |
12082 CONVERT_CHECKED(JSObject, target, args[0]); | 12055 CONVERT_CHECKED(JSObject, target, args[0]); |
12083 Object* instance_filter = args[1]; | 12056 Object* instance_filter = args[1]; |
12084 RUNTIME_ASSERT(instance_filter->IsUndefined() || | 12057 RUNTIME_ASSERT(instance_filter->IsUndefined() || |
12085 instance_filter->IsJSObject()); | 12058 instance_filter->IsJSObject()); |
12086 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]); | 12059 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]); |
12087 RUNTIME_ASSERT(max_references >= 0); | 12060 RUNTIME_ASSERT(max_references >= 0); |
12088 | 12061 |
| 12062 |
12089 // Get the constructor function for context extension and arguments array. | 12063 // Get the constructor function for context extension and arguments array. |
12090 JSObject* arguments_boilerplate = | 12064 JSObject* arguments_boilerplate = |
12091 isolate->context()->global_context()->arguments_boilerplate(); | 12065 isolate->context()->global_context()->arguments_boilerplate(); |
12092 JSFunction* arguments_function = | 12066 JSFunction* arguments_function = |
12093 JSFunction::cast(arguments_boilerplate->map()->constructor()); | 12067 JSFunction::cast(arguments_boilerplate->map()->constructor()); |
12094 | 12068 |
12095 // Get the number of referencing objects. | 12069 // Get the number of referencing objects. |
12096 int count; | 12070 int count; |
12097 count = DebugReferencedBy(target, instance_filter, max_references, | 12071 HeapIterator heap_iterator; |
| 12072 count = DebugReferencedBy(&heap_iterator, |
| 12073 target, instance_filter, max_references, |
12098 NULL, 0, arguments_function); | 12074 NULL, 0, arguments_function); |
12099 | 12075 |
12100 // Allocate an array to hold the result. | 12076 // Allocate an array to hold the result. |
12101 Object* object; | 12077 Object* object; |
12102 { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count); | 12078 { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count); |
12103 if (!maybe_object->ToObject(&object)) return maybe_object; | 12079 if (!maybe_object->ToObject(&object)) return maybe_object; |
12104 } | 12080 } |
12105 FixedArray* instances = FixedArray::cast(object); | 12081 FixedArray* instances = FixedArray::cast(object); |
12106 | 12082 |
12107 // Fill the referencing objects. | 12083 // Fill the referencing objects. |
12108 count = DebugReferencedBy(target, instance_filter, max_references, | 12084 // AllocateFixedArray above does not make the heap non-iterable. |
| 12085 ASSERT(HEAP->IsHeapIterable()); |
| 12086 HeapIterator heap_iterator2; |
| 12087 count = DebugReferencedBy(&heap_iterator2, |
| 12088 target, instance_filter, max_references, |
12109 instances, count, arguments_function); | 12089 instances, count, arguments_function); |
12110 | 12090 |
12111 // Return result as JS array. | 12091 // Return result as JS array. |
12112 Object* result; | 12092 Object* result; |
12113 { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject( | 12093 MaybeObject* maybe_result = isolate->heap()->AllocateJSObject( |
12114 isolate->context()->global_context()->array_function()); | 12094 isolate->context()->global_context()->array_function()); |
12115 if (!maybe_result->ToObject(&result)) return maybe_result; | 12095 if (!maybe_result->ToObject(&result)) return maybe_result; |
12116 } | 12096 return JSArray::cast(result)->SetContent(instances); |
12117 JSArray::cast(result)->SetContent(instances); | |
12118 return result; | |
12119 } | 12097 } |
12120 | 12098 |
12121 | 12099 |
12122 // Helper function used by Runtime_DebugConstructedBy below. | 12100 // Helper function used by Runtime_DebugConstructedBy below. |
12123 static int DebugConstructedBy(JSFunction* constructor, int max_references, | 12101 static int DebugConstructedBy(HeapIterator* iterator, |
12124 FixedArray* instances, int instances_size) { | 12102 JSFunction* constructor, |
| 12103 int max_references, |
| 12104 FixedArray* instances, |
| 12105 int instances_size) { |
12125 AssertNoAllocation no_alloc; | 12106 AssertNoAllocation no_alloc; |
12126 | 12107 |
12127 // Iterate the heap. | 12108 // Iterate the heap. |
12128 int count = 0; | 12109 int count = 0; |
12129 HeapIterator iterator; | |
12130 HeapObject* heap_obj = NULL; | 12110 HeapObject* heap_obj = NULL; |
12131 while (((heap_obj = iterator.next()) != NULL) && | 12111 while (((heap_obj = iterator->next()) != NULL) && |
12132 (max_references == 0 || count < max_references)) { | 12112 (max_references == 0 || count < max_references)) { |
12133 // Only look at all JSObjects. | 12113 // Only look at all JSObjects. |
12134 if (heap_obj->IsJSObject()) { | 12114 if (heap_obj->IsJSObject()) { |
12135 JSObject* obj = JSObject::cast(heap_obj); | 12115 JSObject* obj = JSObject::cast(heap_obj); |
12136 if (obj->map()->constructor() == constructor) { | 12116 if (obj->map()->constructor() == constructor) { |
12137 // Valid reference found add to instance array if supplied an update | 12117 // Valid reference found add to instance array if supplied an update |
12138 // count. | 12118 // count. |
12139 if (instances != NULL && count < instances_size) { | 12119 if (instances != NULL && count < instances_size) { |
12140 instances->set(count, obj); | 12120 instances->set(count, obj); |
12141 } | 12121 } |
12142 count++; | 12122 count++; |
12143 } | 12123 } |
12144 } | 12124 } |
12145 } | 12125 } |
12146 | 12126 |
12147 // Return the number of referencing objects found. | 12127 // Return the number of referencing objects found. |
12148 return count; | 12128 return count; |
12149 } | 12129 } |
12150 | 12130 |
12151 | 12131 |
12152 // Scan the heap for objects constructed by a specific function. | 12132 // Scan the heap for objects constructed by a specific function. |
12153 // args[0]: the constructor to find instances of | 12133 // args[0]: the constructor to find instances of |
12154 // args[1]: the the maximum number of objects to return | 12134 // args[1]: the the maximum number of objects to return |
12155 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) { | 12135 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) { |
12156 ASSERT(args.length() == 2); | 12136 ASSERT(args.length() == 2); |
12157 | 12137 |
12158 // First perform a full GC in order to avoid dead objects. | 12138 // First perform a full GC in order to avoid dead objects. |
12159 isolate->heap()->CollectAllGarbage(false); | 12139 isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
12160 | 12140 |
12161 // Check parameters. | 12141 // Check parameters. |
12162 CONVERT_CHECKED(JSFunction, constructor, args[0]); | 12142 CONVERT_CHECKED(JSFunction, constructor, args[0]); |
12163 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]); | 12143 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]); |
12164 RUNTIME_ASSERT(max_references >= 0); | 12144 RUNTIME_ASSERT(max_references >= 0); |
12165 | 12145 |
12166 // Get the number of referencing objects. | 12146 // Get the number of referencing objects. |
12167 int count; | 12147 int count; |
12168 count = DebugConstructedBy(constructor, max_references, NULL, 0); | 12148 HeapIterator heap_iterator; |
| 12149 count = DebugConstructedBy(&heap_iterator, |
| 12150 constructor, |
| 12151 max_references, |
| 12152 NULL, |
| 12153 0); |
12169 | 12154 |
12170 // Allocate an array to hold the result. | 12155 // Allocate an array to hold the result. |
12171 Object* object; | 12156 Object* object; |
12172 { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count); | 12157 { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count); |
12173 if (!maybe_object->ToObject(&object)) return maybe_object; | 12158 if (!maybe_object->ToObject(&object)) return maybe_object; |
12174 } | 12159 } |
12175 FixedArray* instances = FixedArray::cast(object); | 12160 FixedArray* instances = FixedArray::cast(object); |
12176 | 12161 |
| 12162 ASSERT(HEAP->IsHeapIterable()); |
12177 // Fill the referencing objects. | 12163 // Fill the referencing objects. |
12178 count = DebugConstructedBy(constructor, max_references, instances, count); | 12164 HeapIterator heap_iterator2; |
| 12165 count = DebugConstructedBy(&heap_iterator2, |
| 12166 constructor, |
| 12167 max_references, |
| 12168 instances, |
| 12169 count); |
12179 | 12170 |
12180 // Return result as JS array. | 12171 // Return result as JS array. |
12181 Object* result; | 12172 Object* result; |
12182 { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject( | 12173 { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject( |
12183 isolate->context()->global_context()->array_function()); | 12174 isolate->context()->global_context()->array_function()); |
12184 if (!maybe_result->ToObject(&result)) return maybe_result; | 12175 if (!maybe_result->ToObject(&result)) return maybe_result; |
12185 } | 12176 } |
12186 JSArray::cast(result)->SetContent(instances); | 12177 return JSArray::cast(result)->SetContent(instances); |
12187 return result; | |
12188 } | 12178 } |
12189 | 12179 |
12190 | 12180 |
12191 // Find the effective prototype object as returned by __proto__. | 12181 // Find the effective prototype object as returned by __proto__. |
12192 // args[0]: the object to find the prototype for. | 12182 // args[0]: the object to find the prototype for. |
12193 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) { | 12183 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) { |
12194 ASSERT(args.length() == 1); | 12184 ASSERT(args.length() == 1); |
12195 | 12185 |
12196 CONVERT_CHECKED(JSObject, obj, args[0]); | 12186 CONVERT_CHECKED(JSObject, obj, args[0]); |
12197 | 12187 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12241 | 12231 |
12242 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) { | 12232 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) { |
12243 NoHandleAllocation ha; | 12233 NoHandleAllocation ha; |
12244 ASSERT(args.length() == 1); | 12234 ASSERT(args.length() == 1); |
12245 | 12235 |
12246 CONVERT_CHECKED(JSFunction, f, args[0]); | 12236 CONVERT_CHECKED(JSFunction, f, args[0]); |
12247 return f->shared()->inferred_name(); | 12237 return f->shared()->inferred_name(); |
12248 } | 12238 } |
12249 | 12239 |
12250 | 12240 |
12251 static int FindSharedFunctionInfosForScript(Script* script, | 12241 static int FindSharedFunctionInfosForScript(HeapIterator* iterator, |
| 12242 Script* script, |
12252 FixedArray* buffer) { | 12243 FixedArray* buffer) { |
12253 AssertNoAllocation no_allocations; | 12244 AssertNoAllocation no_allocations; |
12254 | |
12255 int counter = 0; | 12245 int counter = 0; |
12256 int buffer_size = buffer->length(); | 12246 int buffer_size = buffer->length(); |
12257 HeapIterator iterator; | 12247 for (HeapObject* obj = iterator->next(); |
12258 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 12248 obj != NULL; |
| 12249 obj = iterator->next()) { |
12259 ASSERT(obj != NULL); | 12250 ASSERT(obj != NULL); |
12260 if (!obj->IsSharedFunctionInfo()) { | 12251 if (!obj->IsSharedFunctionInfo()) { |
12261 continue; | 12252 continue; |
12262 } | 12253 } |
12263 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 12254 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
12264 if (shared->script() != script) { | 12255 if (shared->script() != script) { |
12265 continue; | 12256 continue; |
12266 } | 12257 } |
12267 if (counter < buffer_size) { | 12258 if (counter < buffer_size) { |
12268 buffer->set(counter, shared); | 12259 buffer->set(counter, shared); |
12269 } | 12260 } |
12270 counter++; | 12261 counter++; |
12271 } | 12262 } |
12272 return counter; | 12263 return counter; |
12273 } | 12264 } |
12274 | 12265 |
12275 // For a script finds all SharedFunctionInfo's in the heap that points | 12266 // For a script finds all SharedFunctionInfo's in the heap that points |
12276 // to this script. Returns JSArray of SharedFunctionInfo wrapped | 12267 // to this script. Returns JSArray of SharedFunctionInfo wrapped |
12277 // in OpaqueReferences. | 12268 // in OpaqueReferences. |
12278 RUNTIME_FUNCTION(MaybeObject*, | 12269 RUNTIME_FUNCTION(MaybeObject*, |
12279 Runtime_LiveEditFindSharedFunctionInfosForScript) { | 12270 Runtime_LiveEditFindSharedFunctionInfosForScript) { |
12280 ASSERT(args.length() == 1); | 12271 ASSERT(args.length() == 1); |
12281 HandleScope scope(isolate); | 12272 HandleScope scope(isolate); |
12282 CONVERT_CHECKED(JSValue, script_value, args[0]); | 12273 CONVERT_CHECKED(JSValue, script_value, args[0]); |
12283 | 12274 |
| 12275 |
12284 Handle<Script> script = Handle<Script>(Script::cast(script_value->value())); | 12276 Handle<Script> script = Handle<Script>(Script::cast(script_value->value())); |
12285 | 12277 |
12286 const int kBufferSize = 32; | 12278 const int kBufferSize = 32; |
12287 | 12279 |
12288 Handle<FixedArray> array; | 12280 Handle<FixedArray> array; |
12289 array = isolate->factory()->NewFixedArray(kBufferSize); | 12281 array = isolate->factory()->NewFixedArray(kBufferSize); |
12290 int number = FindSharedFunctionInfosForScript(*script, *array); | 12282 int number; |
| 12283 { |
| 12284 isolate->heap()->EnsureHeapIsIterable(); |
| 12285 AssertNoAllocation no_allocations; |
| 12286 HeapIterator heap_iterator; |
| 12287 Script* scr = *script; |
| 12288 FixedArray* arr = *array; |
| 12289 number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr); |
| 12290 } |
12291 if (number > kBufferSize) { | 12291 if (number > kBufferSize) { |
12292 array = isolate->factory()->NewFixedArray(number); | 12292 array = isolate->factory()->NewFixedArray(number); |
12293 FindSharedFunctionInfosForScript(*script, *array); | 12293 isolate->heap()->EnsureHeapIsIterable(); |
| 12294 AssertNoAllocation no_allocations; |
| 12295 HeapIterator heap_iterator; |
| 12296 Script* scr = *script; |
| 12297 FixedArray* arr = *array; |
| 12298 FindSharedFunctionInfosForScript(&heap_iterator, scr, arr); |
12294 } | 12299 } |
12295 | 12300 |
12296 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array); | 12301 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array); |
12297 result->set_length(Smi::FromInt(number)); | 12302 result->set_length(Smi::FromInt(number)); |
12298 | 12303 |
12299 LiveEdit::WrapSharedFunctionInfos(result); | 12304 LiveEdit::WrapSharedFunctionInfos(result); |
12300 | 12305 |
12301 return *result; | 12306 return *result; |
12302 } | 12307 } |
12303 | 12308 |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12764 // heap traversal to find the function generated for the source position | 12769 // heap traversal to find the function generated for the source position |
12765 // for the requested break point. For lazily compiled functions several heap | 12770 // for the requested break point. For lazily compiled functions several heap |
12766 // traversals might be required rendering this operation as a rather slow | 12771 // traversals might be required rendering this operation as a rather slow |
12767 // operation. However for setting break points which is normally done through | 12772 // operation. However for setting break points which is normally done through |
12768 // some kind of user interaction the performance is not crucial. | 12773 // some kind of user interaction the performance is not crucial. |
12769 static Handle<Object> Runtime_GetScriptFromScriptName( | 12774 static Handle<Object> Runtime_GetScriptFromScriptName( |
12770 Handle<String> script_name) { | 12775 Handle<String> script_name) { |
12771 // Scan the heap for Script objects to find the script with the requested | 12776 // Scan the heap for Script objects to find the script with the requested |
12772 // script data. | 12777 // script data. |
12773 Handle<Script> script; | 12778 Handle<Script> script; |
| 12779 script_name->GetHeap()->EnsureHeapIsIterable(); |
| 12780 AssertNoAllocation no_allocation_during_heap_iteration; |
12774 HeapIterator iterator; | 12781 HeapIterator iterator; |
12775 HeapObject* obj = NULL; | 12782 HeapObject* obj = NULL; |
12776 while (script.is_null() && ((obj = iterator.next()) != NULL)) { | 12783 while (script.is_null() && ((obj = iterator.next()) != NULL)) { |
12777 // If a script is found check if it has the script data requested. | 12784 // If a script is found check if it has the script data requested. |
12778 if (obj->IsScript()) { | 12785 if (obj->IsScript()) { |
12779 if (Script::cast(obj)->name()->IsString()) { | 12786 if (Script::cast(obj)->name()->IsString()) { |
12780 if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) { | 12787 if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) { |
12781 script = Handle<Script>(Script::cast(obj)); | 12788 script = Handle<Script>(Script::cast(obj)); |
12782 } | 12789 } |
12783 } | 12790 } |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12976 Handle<JSFunctionResultCache> cache_handle(cache); | 12983 Handle<JSFunctionResultCache> cache_handle(cache); |
12977 Handle<Object> key_handle(key); | 12984 Handle<Object> key_handle(key); |
12978 Handle<Object> value; | 12985 Handle<Object> value; |
12979 { | 12986 { |
12980 Handle<JSFunction> factory(JSFunction::cast( | 12987 Handle<JSFunction> factory(JSFunction::cast( |
12981 cache_handle->get(JSFunctionResultCache::kFactoryIndex))); | 12988 cache_handle->get(JSFunctionResultCache::kFactoryIndex))); |
12982 // TODO(antonm): consider passing a receiver when constructing a cache. | 12989 // TODO(antonm): consider passing a receiver when constructing a cache. |
12983 Handle<Object> receiver(isolate->global_context()->global()); | 12990 Handle<Object> receiver(isolate->global_context()->global()); |
12984 // This handle is nor shared, nor used later, so it's safe. | 12991 // This handle is nor shared, nor used later, so it's safe. |
12985 Object** argv[] = { key_handle.location() }; | 12992 Object** argv[] = { key_handle.location() }; |
12986 bool pending_exception = false; | 12993 bool pending_exception; |
12987 value = Execution::Call(factory, | 12994 value = Execution::Call(factory, |
12988 receiver, | 12995 receiver, |
12989 1, | 12996 1, |
12990 argv, | 12997 argv, |
12991 &pending_exception); | 12998 &pending_exception); |
12992 if (pending_exception) return Failure::Exception(); | 12999 if (pending_exception) return Failure::Exception(); |
12993 } | 13000 } |
12994 | 13001 |
12995 #ifdef DEBUG | 13002 #ifdef DEBUG |
12996 cache_handle->JSFunctionResultCacheVerify(); | 13003 cache_handle->JSFunctionResultCacheVerify(); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13132 return NULL; | 13139 return NULL; |
13133 } | 13140 } |
13134 | 13141 |
13135 | 13142 |
13136 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \ | 13143 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \ |
13137 RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \ | 13144 RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \ |
13138 CONVERT_CHECKED(JSObject, obj, args[0]); \ | 13145 CONVERT_CHECKED(JSObject, obj, args[0]); \ |
13139 return isolate->heap()->ToBoolean(obj->Has##Name()); \ | 13146 return isolate->heap()->ToBoolean(obj->Has##Name()); \ |
13140 } | 13147 } |
13141 | 13148 |
| 13149 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOnlyElements) |
13142 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements) | 13150 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements) |
13143 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements) | 13151 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements) |
13144 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements) | 13152 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements) |
13145 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements) | 13153 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements) |
13146 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements) | 13154 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements) |
13147 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements) | 13155 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements) |
13148 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements) | 13156 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements) |
13149 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements) | 13157 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements) |
13150 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements) | 13158 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements) |
13151 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements) | 13159 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements) |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13215 | 13223 |
13216 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 13224 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
13217 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 13225 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
13218 } | 13226 } |
13219 | 13227 |
13220 | 13228 |
13221 void Runtime::PerformGC(Object* result) { | 13229 void Runtime::PerformGC(Object* result) { |
13222 Isolate* isolate = Isolate::Current(); | 13230 Isolate* isolate = Isolate::Current(); |
13223 Failure* failure = Failure::cast(result); | 13231 Failure* failure = Failure::cast(result); |
13224 if (failure->IsRetryAfterGC()) { | 13232 if (failure->IsRetryAfterGC()) { |
| 13233 if (isolate->heap()->new_space()->AddFreshPage()) { |
| 13234 return; |
| 13235 } |
13225 // Try to do a garbage collection; ignore it if it fails. The C | 13236 // Try to do a garbage collection; ignore it if it fails. The C |
13226 // entry stub will throw an out-of-memory exception in that case. | 13237 // entry stub will throw an out-of-memory exception in that case. |
13227 isolate->heap()->CollectGarbage(failure->allocation_space()); | 13238 isolate->heap()->CollectGarbage(failure->allocation_space()); |
13228 } else { | 13239 } else { |
13229 // Handle last resort GC and make sure to allow future allocations | 13240 // Handle last resort GC and make sure to allow future allocations |
13230 // to grow the heap without causing GCs (if possible). | 13241 // to grow the heap without causing GCs (if possible). |
13231 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13242 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13232 isolate->heap()->CollectAllGarbage(false); | 13243 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
13233 } | 13244 } |
13234 } | 13245 } |
13235 | 13246 |
13236 | 13247 |
13237 } } // namespace v8::internal | 13248 } } // namespace v8::internal |
OLD | NEW |