| 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 1284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1295 ASSERT(!isolate->has_pending_exception()); | 1295 ASSERT(!isolate->has_pending_exception()); |
| 1296 return isolate->heap()->undefined_value(); | 1296 return isolate->heap()->undefined_value(); |
| 1297 } | 1297 } |
| 1298 | 1298 |
| 1299 | 1299 |
| 1300 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { | 1300 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { |
| 1301 HandleScope scope(isolate); | 1301 HandleScope scope(isolate); |
| 1302 ASSERT(args.length() == 4); | 1302 ASSERT(args.length() == 4); |
| 1303 | 1303 |
| 1304 CONVERT_ARG_CHECKED(Context, context, 0); | 1304 CONVERT_ARG_CHECKED(Context, context, 0); |
| 1305 // Declarations are always done in a function or global context. |
| 1306 ASSERT(context->IsFunctionContext() || context->IsGlobalContext()); |
| 1307 |
| 1305 Handle<String> name(String::cast(args[1])); | 1308 Handle<String> name(String::cast(args[1])); |
| 1306 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2)); | 1309 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2)); |
| 1307 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); | 1310 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); |
| 1308 Handle<Object> initial_value(args[3], isolate); | 1311 Handle<Object> initial_value(args[3], isolate); |
| 1309 | 1312 |
| 1310 // Declarations are always done in a function or global context. | |
| 1311 context = Handle<Context>(context->declaration_context()); | |
| 1312 | |
| 1313 int index; | 1313 int index; |
| 1314 PropertyAttributes attributes; | 1314 PropertyAttributes attributes; |
| 1315 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; | 1315 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; |
| 1316 BindingFlags binding_flags; | 1316 BindingFlags binding_flags; |
| 1317 Handle<Object> holder = | 1317 Handle<Object> holder = |
| 1318 context->Lookup(name, flags, &index, &attributes, &binding_flags); | 1318 context->Lookup(name, flags, &index, &attributes, &binding_flags); |
| 1319 | 1319 |
| 1320 if (attributes != ABSENT) { | 1320 if (attributes != ABSENT) { |
| 1321 // The name was declared before; check for conflicting | 1321 // The name was declared before; check for conflicting re-declarations. |
| 1322 // re-declarations: This is similar to the code in parser.cc in | |
| 1323 // the AstBuildingParser::Declare function. | |
| 1324 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) { | 1322 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) { |
| 1325 // Functions are not read-only. | 1323 // Functions are not read-only. |
| 1326 ASSERT(mode != READ_ONLY || initial_value->IsTheHole()); | 1324 ASSERT(mode != READ_ONLY || initial_value->IsTheHole()); |
| 1327 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var"; | 1325 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var"; |
| 1328 return ThrowRedeclarationError(isolate, type, name); | 1326 return ThrowRedeclarationError(isolate, type, name); |
| 1329 } | 1327 } |
| 1330 | 1328 |
| 1331 // Initialize it if necessary. | 1329 // Initialize it if necessary. |
| 1332 if (*initial_value != NULL) { | 1330 if (*initial_value != NULL) { |
| 1333 if (index >= 0) { | 1331 if (index >= 0) { |
| 1334 // The variable or constant context slot should always be in | 1332 ASSERT(holder.is_identical_to(context)); |
| 1335 // the function context or the arguments object. | 1333 if (((attributes & READ_ONLY) == 0) || |
| 1336 if (holder->IsContext()) { | 1334 context->get(index)->IsTheHole()) { |
| 1337 ASSERT(holder.is_identical_to(context)); | 1335 context->set(index, *initial_value); |
| 1338 if (((attributes & READ_ONLY) == 0) || | |
| 1339 context->get(index)->IsTheHole()) { | |
| 1340 context->set(index, *initial_value); | |
| 1341 } | |
| 1342 } else { | |
| 1343 // The holder is an arguments object. | |
| 1344 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | |
| 1345 Handle<Object> result = SetElement(arguments, index, initial_value, | |
| 1346 kNonStrictMode); | |
| 1347 if (result.is_null()) return Failure::Exception(); | |
| 1348 } | 1336 } |
| 1349 } else { | 1337 } else { |
| 1350 // Slow case: The property is not in the FixedArray part of the context. | 1338 // Slow case: The property is in the context extension object of a |
| 1351 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); | 1339 // function context or the global object of a global context. |
| 1340 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
| 1352 RETURN_IF_EMPTY_HANDLE( | 1341 RETURN_IF_EMPTY_HANDLE( |
| 1353 isolate, | 1342 isolate, |
| 1354 SetProperty(context_ext, name, initial_value, | 1343 SetProperty(object, name, initial_value, mode, kNonStrictMode)); |
| 1355 mode, kNonStrictMode)); | |
| 1356 } | 1344 } |
| 1357 } | 1345 } |
| 1358 | 1346 |
| 1359 } else { | 1347 } else { |
| 1360 // The property is not in the function context. It needs to be | 1348 // The property is not in the function context. It needs to be |
| 1361 // "declared" in the function context's extension context, or in the | 1349 // "declared" in the function context's extension context or as a |
| 1362 // global context. | 1350 // property of the the global object. |
| 1363 Handle<JSObject> context_ext; | 1351 Handle<JSObject> object; |
| 1364 if (context->has_extension()) { | 1352 if (context->has_extension()) { |
| 1365 // The function context's extension context exists - use it. | 1353 object = Handle<JSObject>(JSObject::cast(context->extension())); |
| 1366 context_ext = Handle<JSObject>(JSObject::cast(context->extension())); | |
| 1367 } else { | 1354 } else { |
| 1368 // The function context's extension context does not exists - allocate | 1355 // Context extension objects are allocated lazily. |
| 1369 // it. | 1356 ASSERT(context->IsFunctionContext()); |
| 1370 context_ext = isolate->factory()->NewJSObject( | 1357 object = isolate->factory()->NewJSObject( |
| 1371 isolate->context_extension_function()); | 1358 isolate->context_extension_function()); |
| 1372 // And store it in the extension slot. | 1359 context->set_extension(*object); |
| 1373 context->set_extension(*context_ext); | |
| 1374 } | 1360 } |
| 1375 ASSERT(*context_ext != NULL); | 1361 ASSERT(*object != NULL); |
| 1376 | 1362 |
| 1377 // Declare the property by setting it to the initial value if provided, | 1363 // Declare the property by setting it to the initial value if provided, |
| 1378 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for | 1364 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for |
| 1379 // constant declarations). | 1365 // constant declarations). |
| 1380 ASSERT(!context_ext->HasLocalProperty(*name)); | 1366 ASSERT(!object->HasLocalProperty(*name)); |
| 1381 Handle<Object> value(isolate->heap()->undefined_value(), isolate); | 1367 Handle<Object> value(isolate->heap()->undefined_value(), isolate); |
| 1382 if (*initial_value != NULL) value = initial_value; | 1368 if (*initial_value != NULL) value = initial_value; |
| 1383 // Declaring a const context slot is a conflicting declaration if | 1369 // Declaring a const context slot is a conflicting declaration if |
| 1384 // there is a callback with that name in a prototype. It is | 1370 // there is a callback with that name in a prototype. It is |
| 1385 // allowed to introduce const variables in | 1371 // allowed to introduce const variables in |
| 1386 // JSContextExtensionObjects. They are treated specially in | 1372 // JSContextExtensionObjects. They are treated specially in |
| 1387 // SetProperty and no setters are invoked for those since they are | 1373 // SetProperty and no setters are invoked for those since they are |
| 1388 // not real JSObjects. | 1374 // not real JSObjects. |
| 1389 if (initial_value->IsTheHole() && | 1375 if (initial_value->IsTheHole() && |
| 1390 !context_ext->IsJSContextExtensionObject()) { | 1376 !object->IsJSContextExtensionObject()) { |
| 1391 LookupResult lookup; | 1377 LookupResult lookup; |
| 1392 context_ext->Lookup(*name, &lookup); | 1378 object->Lookup(*name, &lookup); |
| 1393 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) { | 1379 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) { |
| 1394 return ThrowRedeclarationError(isolate, "const", name); | 1380 return ThrowRedeclarationError(isolate, "const", name); |
| 1395 } | 1381 } |
| 1396 } | 1382 } |
| 1397 RETURN_IF_EMPTY_HANDLE(isolate, | 1383 RETURN_IF_EMPTY_HANDLE(isolate, |
| 1398 SetProperty(context_ext, name, value, mode, | 1384 SetProperty(object, name, value, mode, |
| 1399 kNonStrictMode)); | 1385 kNonStrictMode)); |
| 1400 } | 1386 } |
| 1401 | 1387 |
| 1402 return isolate->heap()->undefined_value(); | 1388 return isolate->heap()->undefined_value(); |
| 1403 } | 1389 } |
| 1404 | 1390 |
| 1405 | 1391 |
| 1406 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { | 1392 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { |
| 1407 NoHandleAllocation nha; | 1393 NoHandleAllocation nha; |
| 1408 // args[0] == name | 1394 // args[0] == name |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1586 return *value; | 1572 return *value; |
| 1587 } | 1573 } |
| 1588 | 1574 |
| 1589 | 1575 |
| 1590 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { | 1576 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { |
| 1591 HandleScope scope(isolate); | 1577 HandleScope scope(isolate); |
| 1592 ASSERT(args.length() == 3); | 1578 ASSERT(args.length() == 3); |
| 1593 | 1579 |
| 1594 Handle<Object> value(args[0], isolate); | 1580 Handle<Object> value(args[0], isolate); |
| 1595 ASSERT(!value->IsTheHole()); | 1581 ASSERT(!value->IsTheHole()); |
| 1596 CONVERT_ARG_CHECKED(Context, context, 1); | |
| 1597 Handle<String> name(String::cast(args[2])); | |
| 1598 | 1582 |
| 1599 // Initializations are always done in a function or global context. | 1583 // Initializations are always done in a function or global context. |
| 1600 context = Handle<Context>(context->declaration_context()); | 1584 RUNTIME_ASSERT(args[1]->IsContext()); |
| 1585 Handle<Context> context(Context::cast(args[1])->declaration_context()); |
| 1586 |
| 1587 Handle<String> name(String::cast(args[2])); |
| 1601 | 1588 |
| 1602 int index; | 1589 int index; |
| 1603 PropertyAttributes attributes; | 1590 PropertyAttributes attributes; |
| 1604 ContextLookupFlags flags = FOLLOW_CHAINS; | 1591 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 1605 BindingFlags binding_flags; | 1592 BindingFlags binding_flags; |
| 1606 Handle<Object> holder = | 1593 Handle<Object> holder = |
| 1607 context->Lookup(name, flags, &index, &attributes, &binding_flags); | 1594 context->Lookup(name, flags, &index, &attributes, &binding_flags); |
| 1608 | 1595 |
| 1609 // In most situations, the property introduced by the const | |
| 1610 // declaration should be present in the context extension object. | |
| 1611 // However, because declaration and initialization are separate, the | |
| 1612 // property might have been deleted (if it was introduced by eval) | |
| 1613 // before we reach the initialization point. | |
| 1614 // | |
| 1615 // Example: | |
| 1616 // | |
| 1617 // function f() { eval("delete x; const x;"); } | |
| 1618 // | |
| 1619 // In that case, the initialization behaves like a normal assignment | |
| 1620 // to property 'x'. | |
| 1621 if (index >= 0) { | 1596 if (index >= 0) { |
| 1622 if (holder->IsContext()) { | 1597 ASSERT(holder->IsContext()); |
| 1623 // Property was found in a context. Perform the assignment if we | 1598 // Property was found in a context. Perform the assignment if we |
| 1624 // found some non-constant or an uninitialized constant. | 1599 // found some non-constant or an uninitialized constant. |
| 1625 Handle<Context> context = Handle<Context>::cast(holder); | 1600 Handle<Context> context = Handle<Context>::cast(holder); |
| 1626 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) { | 1601 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) { |
| 1627 context->set(index, *value); | 1602 context->set(index, *value); |
| 1628 } | |
| 1629 } else { | |
| 1630 // The holder is an arguments object. | |
| 1631 ASSERT((attributes & READ_ONLY) == 0); | |
| 1632 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | |
| 1633 RETURN_IF_EMPTY_HANDLE( | |
| 1634 isolate, | |
| 1635 SetElement(arguments, index, value, kNonStrictMode)); | |
| 1636 } | 1603 } |
| 1637 return *value; | 1604 return *value; |
| 1638 } | 1605 } |
| 1639 | 1606 |
| 1640 // The property could not be found, we introduce it in the global | 1607 // The property could not be found, we introduce it as a property of the |
| 1641 // context. | 1608 // global object. |
| 1642 if (attributes == ABSENT) { | 1609 if (attributes == ABSENT) { |
| 1643 Handle<JSObject> global = Handle<JSObject>( | 1610 Handle<JSObject> global = Handle<JSObject>( |
| 1644 isolate->context()->global()); | 1611 isolate->context()->global()); |
| 1645 // Strict mode not needed (const disallowed in strict mode). | 1612 // Strict mode not needed (const disallowed in strict mode). |
| 1646 RETURN_IF_EMPTY_HANDLE( | 1613 RETURN_IF_EMPTY_HANDLE( |
| 1647 isolate, | 1614 isolate, |
| 1648 SetProperty(global, name, value, NONE, kNonStrictMode)); | 1615 SetProperty(global, name, value, NONE, kNonStrictMode)); |
| 1649 return *value; | 1616 return *value; |
| 1650 } | 1617 } |
| 1651 | 1618 |
| 1652 // The property was present in a context extension object. | 1619 // The property was present in some function's context extension object, |
| 1653 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); | 1620 // as a property on the subject of a with, or as a property of the global |
| 1621 // object. |
| 1622 // |
| 1623 // In most situations, eval-introduced consts should still be present in |
| 1624 // the context extension object. However, because declaration and |
| 1625 // initialization are separate, the property might have been deleted |
| 1626 // before we reach the initialization point. |
| 1627 // |
| 1628 // Example: |
| 1629 // |
| 1630 // function f() { eval("delete x; const x;"); } |
| 1631 // |
| 1632 // In that case, the initialization behaves like a normal assignment. |
| 1633 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
| 1654 | 1634 |
| 1655 if (*context_ext == context->extension()) { | 1635 if (*object == context->extension()) { |
| 1656 // This is the property that was introduced by the const | 1636 // This is the property that was introduced by the const declaration. |
| 1657 // declaration. Set it if it hasn't been set before. NOTE: We | 1637 // Set it if it hasn't been set before. NOTE: We cannot use |
| 1658 // cannot use GetProperty() to get the current value as it | 1638 // GetProperty() to get the current value as it 'unholes' the value. |
| 1659 // 'unholes' the value. | |
| 1660 LookupResult lookup; | 1639 LookupResult lookup; |
| 1661 context_ext->LocalLookupRealNamedProperty(*name, &lookup); | 1640 object->LocalLookupRealNamedProperty(*name, &lookup); |
| 1662 ASSERT(lookup.IsProperty()); // the property was declared | 1641 ASSERT(lookup.IsProperty()); // the property was declared |
| 1663 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only | 1642 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only |
| 1664 | 1643 |
| 1665 PropertyType type = lookup.type(); | 1644 PropertyType type = lookup.type(); |
| 1666 if (type == FIELD) { | 1645 if (type == FIELD) { |
| 1667 FixedArray* properties = context_ext->properties(); | 1646 FixedArray* properties = object->properties(); |
| 1668 int index = lookup.GetFieldIndex(); | 1647 int index = lookup.GetFieldIndex(); |
| 1669 if (properties->get(index)->IsTheHole()) { | 1648 if (properties->get(index)->IsTheHole()) { |
| 1670 properties->set(index, *value); | 1649 properties->set(index, *value); |
| 1671 } | 1650 } |
| 1672 } else if (type == NORMAL) { | 1651 } else if (type == NORMAL) { |
| 1673 if (context_ext->GetNormalizedProperty(&lookup)->IsTheHole()) { | 1652 if (object->GetNormalizedProperty(&lookup)->IsTheHole()) { |
| 1674 context_ext->SetNormalizedProperty(&lookup, *value); | 1653 object->SetNormalizedProperty(&lookup, *value); |
| 1675 } | 1654 } |
| 1676 } else { | 1655 } else { |
| 1677 // We should not reach here. Any real, named property should be | 1656 // We should not reach here. Any real, named property should be |
| 1678 // either a field or a dictionary slot. | 1657 // either a field or a dictionary slot. |
| 1679 UNREACHABLE(); | 1658 UNREACHABLE(); |
| 1680 } | 1659 } |
| 1681 } else { | 1660 } else { |
| 1682 // The property was found in a different context extension object. | 1661 // The property was found on some other object. Set it if it is not a |
| 1683 // Set it if it is not a read-only property. | 1662 // read-only property. |
| 1684 if ((attributes & READ_ONLY) == 0) { | 1663 if ((attributes & READ_ONLY) == 0) { |
| 1685 // Strict mode not needed (const disallowed in strict mode). | 1664 // Strict mode not needed (const disallowed in strict mode). |
| 1686 RETURN_IF_EMPTY_HANDLE( | 1665 RETURN_IF_EMPTY_HANDLE( |
| 1687 isolate, | 1666 isolate, |
| 1688 SetProperty(context_ext, name, value, attributes, kNonStrictMode)); | 1667 SetProperty(object, name, value, attributes, kNonStrictMode)); |
| 1689 } | 1668 } |
| 1690 } | 1669 } |
| 1691 | 1670 |
| 1692 return *value; | 1671 return *value; |
| 1693 } | 1672 } |
| 1694 | 1673 |
| 1695 | 1674 |
| 1696 RUNTIME_FUNCTION(MaybeObject*, | 1675 RUNTIME_FUNCTION(MaybeObject*, |
| 1697 Runtime_OptimizeObjectForAddingMultipleProperties) { | 1676 Runtime_OptimizeObjectForAddingMultipleProperties) { |
| 1698 HandleScope scope(isolate); | 1677 HandleScope scope(isolate); |
| (...skipping 6735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8434 if (holder.is_null()) { | 8413 if (holder.is_null()) { |
| 8435 return isolate->heap()->true_value(); | 8414 return isolate->heap()->true_value(); |
| 8436 } | 8415 } |
| 8437 | 8416 |
| 8438 // If the slot was found in a context, it should be DONT_DELETE. | 8417 // If the slot was found in a context, it should be DONT_DELETE. |
| 8439 if (holder->IsContext()) { | 8418 if (holder->IsContext()) { |
| 8440 return isolate->heap()->false_value(); | 8419 return isolate->heap()->false_value(); |
| 8441 } | 8420 } |
| 8442 | 8421 |
| 8443 // The slot was found in a JSObject, either a context extension object, | 8422 // The slot was found in a JSObject, either a context extension object, |
| 8444 // the global object, or an arguments object. Try to delete it | 8423 // the global object, or the subject of a with. Try to delete it |
| 8445 // (respecting DONT_DELETE). For consistency with V8's usual behavior, | 8424 // (respecting DONT_DELETE). |
| 8446 // which allows deleting all parameters in functions that mention | |
| 8447 // 'arguments', we do this even for the case of slots found on an | |
| 8448 // arguments object. The slot was found on an arguments object if the | |
| 8449 // index is non-negative. | |
| 8450 Handle<JSObject> object = Handle<JSObject>::cast(holder); | 8425 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
| 8451 if (index >= 0) { | 8426 return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION); |
| 8452 return object->DeleteElement(index, JSReceiver::NORMAL_DELETION); | |
| 8453 } else { | |
| 8454 return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION); | |
| 8455 } | |
| 8456 } | 8427 } |
| 8457 | 8428 |
| 8458 | 8429 |
| 8459 // A mechanism to return a pair of Object pointers in registers (if possible). | 8430 // A mechanism to return a pair of Object pointers in registers (if possible). |
| 8460 // How this is achieved is calling convention-dependent. | 8431 // How this is achieved is calling convention-dependent. |
| 8461 // All currently supported x86 compiles uses calling conventions that are cdecl | 8432 // All currently supported x86 compiles uses calling conventions that are cdecl |
| 8462 // variants where a 64-bit value is returned in two 32-bit registers | 8433 // variants where a 64-bit value is returned in two 32-bit registers |
| 8463 // (edx:eax on ia32, r1:r0 on ARM). | 8434 // (edx:eax on ia32, r1:r0 on ARM). |
| 8464 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. | 8435 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. |
| 8465 // In Win64 calling convention, a struct of two pointers is returned in memory, | 8436 // 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... |
| 8530 int index; | 8501 int index; |
| 8531 PropertyAttributes attributes; | 8502 PropertyAttributes attributes; |
| 8532 ContextLookupFlags flags = FOLLOW_CHAINS; | 8503 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 8533 BindingFlags binding_flags; | 8504 BindingFlags binding_flags; |
| 8534 Handle<Object> holder = context->Lookup(name, | 8505 Handle<Object> holder = context->Lookup(name, |
| 8535 flags, | 8506 flags, |
| 8536 &index, | 8507 &index, |
| 8537 &attributes, | 8508 &attributes, |
| 8538 &binding_flags); | 8509 &binding_flags); |
| 8539 | 8510 |
| 8540 // If the index is non-negative, the slot has been found in a local | 8511 // If the index is non-negative, the slot has been found in a context. |
| 8541 // variable or a parameter. Read it from the context object or the | |
| 8542 // arguments object. | |
| 8543 if (index >= 0) { | 8512 if (index >= 0) { |
| 8544 // If the "property" we were looking for is a local variable or an | 8513 ASSERT(holder->IsContext()); |
| 8545 // argument in a context, the receiver is the global object; see | 8514 // If the "property" we were looking for is a local variable, the |
| 8546 // ECMA-262, 3rd., 10.1.6 and 10.2.3. | 8515 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3. |
| 8547 // | 8516 // |
| 8548 // Use the hole as the receiver to signal that the receiver is | 8517 // Use the hole as the receiver to signal that the receiver is implicit |
| 8549 // implicit and that the global receiver should be used. | 8518 // and that the global receiver should be used (as distinguished from an |
| 8519 // explicit receiver that happens to be a global object). |
| 8550 Handle<Object> receiver = isolate->factory()->the_hole_value(); | 8520 Handle<Object> receiver = isolate->factory()->the_hole_value(); |
| 8551 MaybeObject* value = (holder->IsContext()) | 8521 Object* value = Context::cast(*holder)->get(index); |
| 8552 ? Context::cast(*holder)->get(index) | |
| 8553 : JSObject::cast(*holder)->GetElement(index); | |
| 8554 // Check for uninitialized bindings. | 8522 // Check for uninitialized bindings. |
| 8555 if (holder->IsContext() && | 8523 if (binding_flags == MUTABLE_CHECK_INITIALIZED && value->IsTheHole()) { |
| 8556 binding_flags == MUTABLE_CHECK_INITIALIZED && | |
| 8557 value->IsTheHole()) { | |
| 8558 Handle<Object> reference_error = | 8524 Handle<Object> reference_error = |
| 8559 isolate->factory()->NewReferenceError("not_defined", | 8525 isolate->factory()->NewReferenceError("not_defined", |
| 8560 HandleVector(&name, 1)); | 8526 HandleVector(&name, 1)); |
| 8561 return MakePair(isolate->Throw(*reference_error), NULL); | 8527 return MakePair(isolate->Throw(*reference_error), NULL); |
| 8562 } else { | 8528 } else { |
| 8563 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); | 8529 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); |
| 8564 } | 8530 } |
| 8565 } | 8531 } |
| 8566 | 8532 |
| 8567 // If the holder is found, we read the property from it. | 8533 // Otherwise, if the slot was found the holder is a context extension |
| 8568 if (!holder.is_null() && holder->IsJSObject()) { | 8534 // object, subject of a with, or a global object. We read the named |
| 8569 ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name)); | 8535 // property from it. |
| 8536 if (!holder.is_null()) { |
| 8570 JSObject* object = JSObject::cast(*holder); | 8537 JSObject* object = JSObject::cast(*holder); |
| 8571 Object* receiver; | 8538 ASSERT(object->HasProperty(*name)); |
| 8572 if (object->IsGlobalObject()) { | 8539 // GetProperty below can cause GC. |
| 8573 receiver = GlobalObject::cast(object)->global_receiver(); | 8540 Handle<Object> receiver_handle(object->IsGlobalObject() |
| 8574 } else if (context->is_exception_holder(*holder)) { | 8541 ? GlobalObject::cast(object)->global_receiver() |
| 8575 // Use the hole as the receiver to signal that the receiver is | 8542 : ComputeReceiverForNonGlobal(isolate, object)); |
| 8576 // implicit and that the global receiver should be used. | |
| 8577 receiver = isolate->heap()->the_hole_value(); | |
| 8578 } else { | |
| 8579 receiver = ComputeReceiverForNonGlobal(isolate, object); | |
| 8580 } | |
| 8581 | 8543 |
| 8582 // GetProperty below can cause GC. | 8544 // No need to unhole the value here. This is taken care of by the |
| 8583 Handle<Object> receiver_handle(receiver); | |
| 8584 | |
| 8585 // No need to unhole the value here. This is taken care of by the | |
| 8586 // GetProperty function. | 8545 // GetProperty function. |
| 8587 MaybeObject* value = object->GetProperty(*name); | 8546 MaybeObject* value = object->GetProperty(*name); |
| 8588 return MakePair(value, *receiver_handle); | 8547 return MakePair(value, *receiver_handle); |
| 8589 } | 8548 } |
| 8590 | 8549 |
| 8591 if (throw_error) { | 8550 if (throw_error) { |
| 8592 // The property doesn't exist - throw exception. | 8551 // The property doesn't exist - throw exception. |
| 8593 Handle<Object> reference_error = | 8552 Handle<Object> reference_error = |
| 8594 isolate->factory()->NewReferenceError("not_defined", | 8553 isolate->factory()->NewReferenceError("not_defined", |
| 8595 HandleVector(&name, 1)); | 8554 HandleVector(&name, 1)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8628 PropertyAttributes attributes; | 8587 PropertyAttributes attributes; |
| 8629 ContextLookupFlags flags = FOLLOW_CHAINS; | 8588 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 8630 BindingFlags binding_flags; | 8589 BindingFlags binding_flags; |
| 8631 Handle<Object> holder = context->Lookup(name, | 8590 Handle<Object> holder = context->Lookup(name, |
| 8632 flags, | 8591 flags, |
| 8633 &index, | 8592 &index, |
| 8634 &attributes, | 8593 &attributes, |
| 8635 &binding_flags); | 8594 &binding_flags); |
| 8636 | 8595 |
| 8637 if (index >= 0) { | 8596 if (index >= 0) { |
| 8638 if (holder->IsContext()) { | 8597 // The property was found in a context slot. |
| 8639 Handle<Context> context = Handle<Context>::cast(holder); | 8598 Handle<Context> context = Handle<Context>::cast(holder); |
| 8640 if (binding_flags == MUTABLE_CHECK_INITIALIZED && | 8599 if (binding_flags == MUTABLE_CHECK_INITIALIZED && |
| 8641 context->get(index)->IsTheHole()) { | 8600 context->get(index)->IsTheHole()) { |
| 8642 Handle<Object> error = | 8601 Handle<Object> error = |
| 8643 isolate->factory()->NewReferenceError("not_defined", | 8602 isolate->factory()->NewReferenceError("not_defined", |
| 8644 HandleVector(&name, 1)); | 8603 HandleVector(&name, 1)); |
| 8645 return isolate->Throw(*error); | 8604 return isolate->Throw(*error); |
| 8646 } | 8605 } |
| 8647 // Ignore if read_only variable. | 8606 // Ignore if read_only variable. |
| 8648 if ((attributes & READ_ONLY) == 0) { | 8607 if ((attributes & READ_ONLY) == 0) { |
| 8649 // Context is a fixed array and set cannot fail. | 8608 // Context is a fixed array and set cannot fail. |
| 8650 context->set(index, *value); | 8609 context->set(index, *value); |
| 8651 } else if (strict_mode == kStrictMode) { | 8610 } else if (strict_mode == kStrictMode) { |
| 8652 // Setting read only property in strict mode. | 8611 // Setting read only property in strict mode. |
| 8653 Handle<Object> error = | 8612 Handle<Object> error = |
| 8654 isolate->factory()->NewTypeError("strict_cannot_assign", | 8613 isolate->factory()->NewTypeError("strict_cannot_assign", |
| 8655 HandleVector(&name, 1)); | 8614 HandleVector(&name, 1)); |
| 8656 return isolate->Throw(*error); | 8615 return isolate->Throw(*error); |
| 8657 } | |
| 8658 } else { | |
| 8659 ASSERT((attributes & READ_ONLY) == 0); | |
| 8660 Handle<Object> result = | |
| 8661 SetElement(Handle<JSObject>::cast(holder), index, value, strict_mode); | |
| 8662 if (result.is_null()) { | |
| 8663 ASSERT(isolate->has_pending_exception()); | |
| 8664 return Failure::Exception(); | |
| 8665 } | |
| 8666 } | 8616 } |
| 8667 return *value; | 8617 return *value; |
| 8668 } | 8618 } |
| 8669 | 8619 |
| 8670 // Slow case: The property is not in a FixedArray context. | 8620 // Slow case: The property is not in a context slot. It is either in a |
| 8671 // It is either in an JSObject extension context or it was not found. | 8621 // context extension object, a property of the subject of a with, or a |
| 8672 Handle<JSObject> context_ext; | 8622 // property of the global object. |
| 8623 Handle<JSObject> object; |
| 8673 | 8624 |
| 8674 if (!holder.is_null()) { | 8625 if (!holder.is_null()) { |
| 8675 // The property exists in the extension context. | 8626 // The property exists on the holder. |
| 8676 context_ext = Handle<JSObject>::cast(holder); | 8627 object = Handle<JSObject>::cast(holder); |
| 8677 } else { | 8628 } else { |
| 8678 // The property was not found. | 8629 // The property was not found. |
| 8679 ASSERT(attributes == ABSENT); | 8630 ASSERT(attributes == ABSENT); |
| 8680 | 8631 |
| 8681 if (strict_mode == kStrictMode) { | 8632 if (strict_mode == kStrictMode) { |
| 8682 // Throw in strict mode (assignment to undefined variable). | 8633 // Throw in strict mode (assignment to undefined variable). |
| 8683 Handle<Object> error = | 8634 Handle<Object> error = |
| 8684 isolate->factory()->NewReferenceError( | 8635 isolate->factory()->NewReferenceError( |
| 8685 "not_defined", HandleVector(&name, 1)); | 8636 "not_defined", HandleVector(&name, 1)); |
| 8686 return isolate->Throw(*error); | 8637 return isolate->Throw(*error); |
| 8687 } | 8638 } |
| 8688 // In non-strict mode, the property is stored in the global context. | 8639 // In non-strict mode, the property is added to the global object. |
| 8689 attributes = NONE; | 8640 attributes = NONE; |
| 8690 context_ext = Handle<JSObject>(isolate->context()->global()); | 8641 object = Handle<JSObject>(isolate->context()->global()); |
| 8691 } | 8642 } |
| 8692 | 8643 |
| 8693 // Set the property, but ignore if read_only variable on the context | 8644 // Set the property if it's not read only or doesn't yet exist. |
| 8694 // extension object itself. | |
| 8695 if ((attributes & READ_ONLY) == 0 || | 8645 if ((attributes & READ_ONLY) == 0 || |
| 8696 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { | 8646 (object->GetLocalPropertyAttribute(*name) == ABSENT)) { |
| 8697 RETURN_IF_EMPTY_HANDLE( | 8647 RETURN_IF_EMPTY_HANDLE( |
| 8698 isolate, | 8648 isolate, |
| 8699 SetProperty(context_ext, name, value, NONE, strict_mode)); | 8649 SetProperty(object, name, value, NONE, strict_mode)); |
| 8700 } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) { | 8650 } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) { |
| 8701 // Setting read only property in strict mode. | 8651 // Setting read only property in strict mode. |
| 8702 Handle<Object> error = | 8652 Handle<Object> error = |
| 8703 isolate->factory()->NewTypeError( | 8653 isolate->factory()->NewTypeError( |
| 8704 "strict_cannot_assign", HandleVector(&name, 1)); | 8654 "strict_cannot_assign", HandleVector(&name, 1)); |
| 8705 return isolate->Throw(*error); | 8655 return isolate->Throw(*error); |
| 8706 } | 8656 } |
| 8707 return *value; | 8657 return *value; |
| 8708 } | 8658 } |
| 8709 | 8659 |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9094 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 9044 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
| 9095 ASSERT(Context::cast(frame->context()) == *context); | 9045 ASSERT(Context::cast(frame->context()) == *context); |
| 9096 #endif | 9046 #endif |
| 9097 | 9047 |
| 9098 // Find where the 'eval' symbol is bound. It is unaliased only if | 9048 // Find where the 'eval' symbol is bound. It is unaliased only if |
| 9099 // it is bound in the global context. | 9049 // it is bound in the global context. |
| 9100 int index = -1; | 9050 int index = -1; |
| 9101 PropertyAttributes attributes = ABSENT; | 9051 PropertyAttributes attributes = ABSENT; |
| 9102 BindingFlags binding_flags; | 9052 BindingFlags binding_flags; |
| 9103 while (true) { | 9053 while (true) { |
| 9054 // Don't follow context chains in Context::Lookup and implement the loop |
| 9055 // up the context chain here, so that we can know the context where eval |
| 9056 // was found. |
| 9104 receiver = context->Lookup(isolate->factory()->eval_symbol(), | 9057 receiver = context->Lookup(isolate->factory()->eval_symbol(), |
| 9105 FOLLOW_PROTOTYPE_CHAIN, | 9058 FOLLOW_PROTOTYPE_CHAIN, |
| 9106 &index, | 9059 &index, |
| 9107 &attributes, | 9060 &attributes, |
| 9108 &binding_flags); | 9061 &binding_flags); |
| 9109 // Stop search when eval is found or when the global context is | 9062 // Stop search when eval is found or when the global context is |
| 9110 // reached. | 9063 // reached. |
| 9111 if (attributes != ABSENT || context->IsGlobalContext()) break; | 9064 if (attributes != ABSENT || context->IsGlobalContext()) break; |
| 9112 context = Handle<Context>(context->previous(), isolate); | 9065 context = Handle<Context>(context->previous(), isolate); |
| 9113 } | 9066 } |
| (...skipping 3908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13022 } else { | 12975 } else { |
| 13023 // Handle last resort GC and make sure to allow future allocations | 12976 // Handle last resort GC and make sure to allow future allocations |
| 13024 // to grow the heap without causing GCs (if possible). | 12977 // to grow the heap without causing GCs (if possible). |
| 13025 isolate->counters()->gc_last_resort_from_js()->Increment(); | 12978 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 13026 isolate->heap()->CollectAllGarbage(false); | 12979 isolate->heap()->CollectAllGarbage(false); |
| 13027 } | 12980 } |
| 13028 } | 12981 } |
| 13029 | 12982 |
| 13030 | 12983 |
| 13031 } } // namespace v8::internal | 12984 } } // namespace v8::internal |
| OLD | NEW |