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 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 | 1294 |
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 // Declarations are always made in a function or global context. In the | 1304 CONVERT_ARG_CHECKED(Context, context, 0); |
1305 // case of eval code, the context passed is the context of the caller, | |
1306 // which may be some nested context and not the declaration context. | |
1307 RUNTIME_ASSERT(args[0]->IsContext()); | |
1308 Handle<Context> context(Context::cast(args[0])->declaration_context()); | |
1309 | |
1310 Handle<String> name(String::cast(args[1])); | 1305 Handle<String> name(String::cast(args[1])); |
1311 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2)); | 1306 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2)); |
1312 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); | 1307 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); |
1313 Handle<Object> initial_value(args[3], isolate); | 1308 Handle<Object> initial_value(args[3], isolate); |
1314 | 1309 |
| 1310 // Declarations are always done in a function or global context. |
| 1311 context = Handle<Context>(context->declaration_context()); |
| 1312 |
1315 int index; | 1313 int index; |
1316 PropertyAttributes attributes; | 1314 PropertyAttributes attributes; |
1317 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; | 1315 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; |
1318 BindingFlags binding_flags; | 1316 BindingFlags binding_flags; |
1319 Handle<Object> holder = | 1317 Handle<Object> holder = |
1320 context->Lookup(name, flags, &index, &attributes, &binding_flags); | 1318 context->Lookup(name, flags, &index, &attributes, &binding_flags); |
1321 | 1319 |
1322 if (attributes != ABSENT) { | 1320 if (attributes != ABSENT) { |
1323 // The name was declared before; check for conflicting re-declarations. | 1321 // The name was declared before; check for conflicting |
| 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)) { | 1324 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) { |
1325 // Functions are not read-only. | 1325 // Functions are not read-only. |
1326 ASSERT(mode != READ_ONLY || initial_value->IsTheHole()); | 1326 ASSERT(mode != READ_ONLY || initial_value->IsTheHole()); |
1327 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var"; | 1327 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var"; |
1328 return ThrowRedeclarationError(isolate, type, name); | 1328 return ThrowRedeclarationError(isolate, type, name); |
1329 } | 1329 } |
1330 | 1330 |
1331 // Initialize it if necessary. | 1331 // Initialize it if necessary. |
1332 if (*initial_value != NULL) { | 1332 if (*initial_value != NULL) { |
1333 if (index >= 0) { | 1333 if (index >= 0) { |
1334 ASSERT(holder.is_identical_to(context)); | 1334 // The variable or constant context slot should always be in |
1335 if (((attributes & READ_ONLY) == 0) || | 1335 // the function context or the arguments object. |
1336 context->get(index)->IsTheHole()) { | 1336 if (holder->IsContext()) { |
1337 context->set(index, *initial_value); | 1337 ASSERT(holder.is_identical_to(context)); |
| 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(); |
1338 } | 1348 } |
1339 } else { | 1349 } else { |
1340 // Slow case: The property is in the context extension object of a | 1350 // Slow case: The property is not in the FixedArray part of the context. |
1341 // function context or the global object of a global context. | 1351 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); |
1342 Handle<JSObject> object = Handle<JSObject>::cast(holder); | |
1343 RETURN_IF_EMPTY_HANDLE( | 1352 RETURN_IF_EMPTY_HANDLE( |
1344 isolate, | 1353 isolate, |
1345 SetProperty(object, name, initial_value, mode, kNonStrictMode)); | 1354 SetProperty(context_ext, name, initial_value, |
| 1355 mode, kNonStrictMode)); |
1346 } | 1356 } |
1347 } | 1357 } |
1348 | 1358 |
1349 } else { | 1359 } else { |
1350 // The property is not in the function context. It needs to be | 1360 // The property is not in the function context. It needs to be |
1351 // "declared" in the function context's extension context or as a | 1361 // "declared" in the function context's extension context, or in the |
1352 // property of the the global object. | 1362 // global context. |
1353 Handle<JSObject> object; | 1363 Handle<JSObject> context_ext; |
1354 if (context->has_extension()) { | 1364 if (context->has_extension()) { |
1355 object = Handle<JSObject>(JSObject::cast(context->extension())); | 1365 // The function context's extension context exists - use it. |
| 1366 context_ext = Handle<JSObject>(JSObject::cast(context->extension())); |
1356 } else { | 1367 } else { |
1357 // Context extension objects are allocated lazily. | 1368 // The function context's extension context does not exists - allocate |
1358 ASSERT(context->IsFunctionContext()); | 1369 // it. |
1359 object = isolate->factory()->NewJSObject( | 1370 context_ext = isolate->factory()->NewJSObject( |
1360 isolate->context_extension_function()); | 1371 isolate->context_extension_function()); |
1361 context->set_extension(*object); | 1372 // And store it in the extension slot. |
| 1373 context->set_extension(*context_ext); |
1362 } | 1374 } |
1363 ASSERT(*object != NULL); | 1375 ASSERT(*context_ext != NULL); |
1364 | 1376 |
1365 // Declare the property by setting it to the initial value if provided, | 1377 // Declare the property by setting it to the initial value if provided, |
1366 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for | 1378 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for |
1367 // constant declarations). | 1379 // constant declarations). |
1368 ASSERT(!object->HasLocalProperty(*name)); | 1380 ASSERT(!context_ext->HasLocalProperty(*name)); |
1369 Handle<Object> value(isolate->heap()->undefined_value(), isolate); | 1381 Handle<Object> value(isolate->heap()->undefined_value(), isolate); |
1370 if (*initial_value != NULL) value = initial_value; | 1382 if (*initial_value != NULL) value = initial_value; |
1371 // Declaring a const context slot is a conflicting declaration if | 1383 // Declaring a const context slot is a conflicting declaration if |
1372 // there is a callback with that name in a prototype. It is | 1384 // there is a callback with that name in a prototype. It is |
1373 // allowed to introduce const variables in | 1385 // allowed to introduce const variables in |
1374 // JSContextExtensionObjects. They are treated specially in | 1386 // JSContextExtensionObjects. They are treated specially in |
1375 // SetProperty and no setters are invoked for those since they are | 1387 // SetProperty and no setters are invoked for those since they are |
1376 // not real JSObjects. | 1388 // not real JSObjects. |
1377 if (initial_value->IsTheHole() && | 1389 if (initial_value->IsTheHole() && |
1378 !object->IsJSContextExtensionObject()) { | 1390 !context_ext->IsJSContextExtensionObject()) { |
1379 LookupResult lookup; | 1391 LookupResult lookup; |
1380 object->Lookup(*name, &lookup); | 1392 context_ext->Lookup(*name, &lookup); |
1381 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) { | 1393 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) { |
1382 return ThrowRedeclarationError(isolate, "const", name); | 1394 return ThrowRedeclarationError(isolate, "const", name); |
1383 } | 1395 } |
1384 } | 1396 } |
1385 RETURN_IF_EMPTY_HANDLE(isolate, | 1397 RETURN_IF_EMPTY_HANDLE(isolate, |
1386 SetProperty(object, name, value, mode, | 1398 SetProperty(context_ext, name, value, mode, |
1387 kNonStrictMode)); | 1399 kNonStrictMode)); |
1388 } | 1400 } |
1389 | 1401 |
1390 return isolate->heap()->undefined_value(); | 1402 return isolate->heap()->undefined_value(); |
1391 } | 1403 } |
1392 | 1404 |
1393 | 1405 |
1394 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { | 1406 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { |
1395 NoHandleAllocation nha; | 1407 NoHandleAllocation nha; |
1396 // args[0] == name | 1408 // args[0] == name |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1574 return *value; | 1586 return *value; |
1575 } | 1587 } |
1576 | 1588 |
1577 | 1589 |
1578 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { | 1590 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { |
1579 HandleScope scope(isolate); | 1591 HandleScope scope(isolate); |
1580 ASSERT(args.length() == 3); | 1592 ASSERT(args.length() == 3); |
1581 | 1593 |
1582 Handle<Object> value(args[0], isolate); | 1594 Handle<Object> value(args[0], isolate); |
1583 ASSERT(!value->IsTheHole()); | 1595 ASSERT(!value->IsTheHole()); |
| 1596 CONVERT_ARG_CHECKED(Context, context, 1); |
| 1597 Handle<String> name(String::cast(args[2])); |
1584 | 1598 |
1585 // Initializations are always done in a function or global context. | 1599 // Initializations are always done in a function or global context. |
1586 RUNTIME_ASSERT(args[1]->IsContext()); | 1600 context = Handle<Context>(context->declaration_context()); |
1587 Handle<Context> context(Context::cast(args[1])->declaration_context()); | |
1588 | |
1589 Handle<String> name(String::cast(args[2])); | |
1590 | 1601 |
1591 int index; | 1602 int index; |
1592 PropertyAttributes attributes; | 1603 PropertyAttributes attributes; |
1593 ContextLookupFlags flags = FOLLOW_CHAINS; | 1604 ContextLookupFlags flags = FOLLOW_CHAINS; |
1594 BindingFlags binding_flags; | 1605 BindingFlags binding_flags; |
1595 Handle<Object> holder = | 1606 Handle<Object> holder = |
1596 context->Lookup(name, flags, &index, &attributes, &binding_flags); | 1607 context->Lookup(name, flags, &index, &attributes, &binding_flags); |
1597 | 1608 |
| 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'. |
1598 if (index >= 0) { | 1621 if (index >= 0) { |
1599 ASSERT(holder->IsContext()); | 1622 if (holder->IsContext()) { |
1600 // Property was found in a context. Perform the assignment if we | 1623 // Property was found in a context. Perform the assignment if we |
1601 // found some non-constant or an uninitialized constant. | 1624 // found some non-constant or an uninitialized constant. |
1602 Handle<Context> context = Handle<Context>::cast(holder); | 1625 Handle<Context> context = Handle<Context>::cast(holder); |
1603 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) { | 1626 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) { |
1604 context->set(index, *value); | 1627 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)); |
1605 } | 1636 } |
1606 return *value; | 1637 return *value; |
1607 } | 1638 } |
1608 | 1639 |
1609 // The property could not be found, we introduce it as a property of the | 1640 // The property could not be found, we introduce it in the global |
1610 // global object. | 1641 // context. |
1611 if (attributes == ABSENT) { | 1642 if (attributes == ABSENT) { |
1612 Handle<JSObject> global = Handle<JSObject>( | 1643 Handle<JSObject> global = Handle<JSObject>( |
1613 isolate->context()->global()); | 1644 isolate->context()->global()); |
1614 // Strict mode not needed (const disallowed in strict mode). | 1645 // Strict mode not needed (const disallowed in strict mode). |
1615 RETURN_IF_EMPTY_HANDLE( | 1646 RETURN_IF_EMPTY_HANDLE( |
1616 isolate, | 1647 isolate, |
1617 SetProperty(global, name, value, NONE, kNonStrictMode)); | 1648 SetProperty(global, name, value, NONE, kNonStrictMode)); |
1618 return *value; | 1649 return *value; |
1619 } | 1650 } |
1620 | 1651 |
1621 // The property was present in some function's context extension object, | 1652 // The property was present in a context extension object. |
1622 // as a property on the subject of a with, or as a property of the global | 1653 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); |
1623 // object. | |
1624 // | |
1625 // In most situations, eval-introduced consts should still be present in | |
1626 // the context extension object. However, because declaration and | |
1627 // initialization are separate, the property might have been deleted | |
1628 // before we reach the initialization point. | |
1629 // | |
1630 // Example: | |
1631 // | |
1632 // function f() { eval("delete x; const x;"); } | |
1633 // | |
1634 // In that case, the initialization behaves like a normal assignment. | |
1635 Handle<JSObject> object = Handle<JSObject>::cast(holder); | |
1636 | 1654 |
1637 if (*object == context->extension()) { | 1655 if (*context_ext == context->extension()) { |
1638 // This is the property that was introduced by the const declaration. | 1656 // This is the property that was introduced by the const |
1639 // Set it if it hasn't been set before. NOTE: We cannot use | 1657 // declaration. Set it if it hasn't been set before. NOTE: We |
1640 // GetProperty() to get the current value as it 'unholes' the value. | 1658 // cannot use GetProperty() to get the current value as it |
| 1659 // 'unholes' the value. |
1641 LookupResult lookup; | 1660 LookupResult lookup; |
1642 object->LocalLookupRealNamedProperty(*name, &lookup); | 1661 context_ext->LocalLookupRealNamedProperty(*name, &lookup); |
1643 ASSERT(lookup.IsProperty()); // the property was declared | 1662 ASSERT(lookup.IsProperty()); // the property was declared |
1644 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only | 1663 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only |
1645 | 1664 |
1646 PropertyType type = lookup.type(); | 1665 PropertyType type = lookup.type(); |
1647 if (type == FIELD) { | 1666 if (type == FIELD) { |
1648 FixedArray* properties = object->properties(); | 1667 FixedArray* properties = context_ext->properties(); |
1649 int index = lookup.GetFieldIndex(); | 1668 int index = lookup.GetFieldIndex(); |
1650 if (properties->get(index)->IsTheHole()) { | 1669 if (properties->get(index)->IsTheHole()) { |
1651 properties->set(index, *value); | 1670 properties->set(index, *value); |
1652 } | 1671 } |
1653 } else if (type == NORMAL) { | 1672 } else if (type == NORMAL) { |
1654 if (object->GetNormalizedProperty(&lookup)->IsTheHole()) { | 1673 if (context_ext->GetNormalizedProperty(&lookup)->IsTheHole()) { |
1655 object->SetNormalizedProperty(&lookup, *value); | 1674 context_ext->SetNormalizedProperty(&lookup, *value); |
1656 } | 1675 } |
1657 } else { | 1676 } else { |
1658 // We should not reach here. Any real, named property should be | 1677 // We should not reach here. Any real, named property should be |
1659 // either a field or a dictionary slot. | 1678 // either a field or a dictionary slot. |
1660 UNREACHABLE(); | 1679 UNREACHABLE(); |
1661 } | 1680 } |
1662 } else { | 1681 } else { |
1663 // The property was found on some other object. Set it if it is not a | 1682 // The property was found in a different context extension object. |
1664 // read-only property. | 1683 // Set it if it is not a read-only property. |
1665 if ((attributes & READ_ONLY) == 0) { | 1684 if ((attributes & READ_ONLY) == 0) { |
1666 // Strict mode not needed (const disallowed in strict mode). | 1685 // Strict mode not needed (const disallowed in strict mode). |
1667 RETURN_IF_EMPTY_HANDLE( | 1686 RETURN_IF_EMPTY_HANDLE( |
1668 isolate, | 1687 isolate, |
1669 SetProperty(object, name, value, attributes, kNonStrictMode)); | 1688 SetProperty(context_ext, name, value, attributes, kNonStrictMode)); |
1670 } | 1689 } |
1671 } | 1690 } |
1672 | 1691 |
1673 return *value; | 1692 return *value; |
1674 } | 1693 } |
1675 | 1694 |
1676 | 1695 |
1677 RUNTIME_FUNCTION(MaybeObject*, | 1696 RUNTIME_FUNCTION(MaybeObject*, |
1678 Runtime_OptimizeObjectForAddingMultipleProperties) { | 1697 Runtime_OptimizeObjectForAddingMultipleProperties) { |
1679 HandleScope scope(isolate); | 1698 HandleScope scope(isolate); |
(...skipping 6857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8537 if (holder.is_null()) { | 8556 if (holder.is_null()) { |
8538 return isolate->heap()->true_value(); | 8557 return isolate->heap()->true_value(); |
8539 } | 8558 } |
8540 | 8559 |
8541 // If the slot was found in a context, it should be DONT_DELETE. | 8560 // If the slot was found in a context, it should be DONT_DELETE. |
8542 if (holder->IsContext()) { | 8561 if (holder->IsContext()) { |
8543 return isolate->heap()->false_value(); | 8562 return isolate->heap()->false_value(); |
8544 } | 8563 } |
8545 | 8564 |
8546 // The slot was found in a JSObject, either a context extension object, | 8565 // The slot was found in a JSObject, either a context extension object, |
8547 // the global object, or the subject of a with. Try to delete it | 8566 // the global object, or an arguments object. Try to delete it |
8548 // (respecting DONT_DELETE). | 8567 // (respecting DONT_DELETE). For consistency with V8's usual behavior, |
| 8568 // which allows deleting all parameters in functions that mention |
| 8569 // 'arguments', we do this even for the case of slots found on an |
| 8570 // arguments object. The slot was found on an arguments object if the |
| 8571 // index is non-negative. |
8549 Handle<JSObject> object = Handle<JSObject>::cast(holder); | 8572 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
8550 return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION); | 8573 if (index >= 0) { |
| 8574 return object->DeleteElement(index, JSReceiver::NORMAL_DELETION); |
| 8575 } else { |
| 8576 return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION); |
| 8577 } |
8551 } | 8578 } |
8552 | 8579 |
8553 | 8580 |
8554 // A mechanism to return a pair of Object pointers in registers (if possible). | 8581 // A mechanism to return a pair of Object pointers in registers (if possible). |
8555 // How this is achieved is calling convention-dependent. | 8582 // How this is achieved is calling convention-dependent. |
8556 // All currently supported x86 compiles uses calling conventions that are cdecl | 8583 // All currently supported x86 compiles uses calling conventions that are cdecl |
8557 // variants where a 64-bit value is returned in two 32-bit registers | 8584 // variants where a 64-bit value is returned in two 32-bit registers |
8558 // (edx:eax on ia32, r1:r0 on ARM). | 8585 // (edx:eax on ia32, r1:r0 on ARM). |
8559 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. | 8586 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. |
8560 // In Win64 calling convention, a struct of two pointers is returned in memory, | 8587 // 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... |
8625 int index; | 8652 int index; |
8626 PropertyAttributes attributes; | 8653 PropertyAttributes attributes; |
8627 ContextLookupFlags flags = FOLLOW_CHAINS; | 8654 ContextLookupFlags flags = FOLLOW_CHAINS; |
8628 BindingFlags binding_flags; | 8655 BindingFlags binding_flags; |
8629 Handle<Object> holder = context->Lookup(name, | 8656 Handle<Object> holder = context->Lookup(name, |
8630 flags, | 8657 flags, |
8631 &index, | 8658 &index, |
8632 &attributes, | 8659 &attributes, |
8633 &binding_flags); | 8660 &binding_flags); |
8634 | 8661 |
8635 // If the index is non-negative, the slot has been found in a context. | 8662 // If the index is non-negative, the slot has been found in a local |
| 8663 // variable or a parameter. Read it from the context object or the |
| 8664 // arguments object. |
8636 if (index >= 0) { | 8665 if (index >= 0) { |
8637 ASSERT(holder->IsContext()); | 8666 // If the "property" we were looking for is a local variable or an |
8638 // If the "property" we were looking for is a local variable, the | 8667 // argument in a context, the receiver is the global object; see |
8639 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3. | 8668 // ECMA-262, 3rd., 10.1.6 and 10.2.3. |
8640 // | 8669 // |
8641 // Use the hole as the receiver to signal that the receiver is implicit | 8670 // Use the hole as the receiver to signal that the receiver is |
8642 // and that the global receiver should be used (as distinguished from an | 8671 // implicit and that the global receiver should be used. |
8643 // explicit receiver that happens to be a global object). | |
8644 Handle<Object> receiver = isolate->factory()->the_hole_value(); | 8672 Handle<Object> receiver = isolate->factory()->the_hole_value(); |
8645 Object* value = Context::cast(*holder)->get(index); | 8673 MaybeObject* value = (holder->IsContext()) |
| 8674 ? Context::cast(*holder)->get(index) |
| 8675 : JSObject::cast(*holder)->GetElement(index); |
8646 // Check for uninitialized bindings. | 8676 // Check for uninitialized bindings. |
8647 if (binding_flags == MUTABLE_CHECK_INITIALIZED && value->IsTheHole()) { | 8677 if (holder->IsContext() && |
| 8678 binding_flags == MUTABLE_CHECK_INITIALIZED && |
| 8679 value->IsTheHole()) { |
8648 Handle<Object> reference_error = | 8680 Handle<Object> reference_error = |
8649 isolate->factory()->NewReferenceError("not_defined", | 8681 isolate->factory()->NewReferenceError("not_defined", |
8650 HandleVector(&name, 1)); | 8682 HandleVector(&name, 1)); |
8651 return MakePair(isolate->Throw(*reference_error), NULL); | 8683 return MakePair(isolate->Throw(*reference_error), NULL); |
8652 } else { | 8684 } else { |
8653 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); | 8685 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); |
8654 } | 8686 } |
8655 } | 8687 } |
8656 | 8688 |
8657 // Otherwise, if the slot was found the holder is a context extension | 8689 // If the holder is found, we read the property from it. |
8658 // object, subject of a with, or a global object. We read the named | 8690 if (!holder.is_null() && holder->IsJSObject()) { |
8659 // property from it. | 8691 ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name)); |
8660 if (!holder.is_null()) { | |
8661 JSObject* object = JSObject::cast(*holder); | 8692 JSObject* object = JSObject::cast(*holder); |
8662 ASSERT(object->HasProperty(*name)); | 8693 Object* receiver; |
| 8694 if (object->IsGlobalObject()) { |
| 8695 receiver = GlobalObject::cast(object)->global_receiver(); |
| 8696 } else if (context->is_exception_holder(*holder)) { |
| 8697 // Use the hole as the receiver to signal that the receiver is |
| 8698 // implicit and that the global receiver should be used. |
| 8699 receiver = isolate->heap()->the_hole_value(); |
| 8700 } else { |
| 8701 receiver = ComputeReceiverForNonGlobal(isolate, object); |
| 8702 } |
| 8703 |
8663 // GetProperty below can cause GC. | 8704 // GetProperty below can cause GC. |
8664 Handle<Object> receiver_handle(object->IsGlobalObject() | 8705 Handle<Object> receiver_handle(receiver); |
8665 ? GlobalObject::cast(object)->global_receiver() | |
8666 : ComputeReceiverForNonGlobal(isolate, object)); | |
8667 | 8706 |
8668 // No need to unhole the value here. This is taken care of by the | 8707 // No need to unhole the value here. This is taken care of by the |
8669 // GetProperty function. | 8708 // GetProperty function. |
8670 MaybeObject* value = object->GetProperty(*name); | 8709 MaybeObject* value = object->GetProperty(*name); |
8671 return MakePair(value, *receiver_handle); | 8710 return MakePair(value, *receiver_handle); |
8672 } | 8711 } |
8673 | 8712 |
8674 if (throw_error) { | 8713 if (throw_error) { |
8675 // The property doesn't exist - throw exception. | 8714 // The property doesn't exist - throw exception. |
8676 Handle<Object> reference_error = | 8715 Handle<Object> reference_error = |
8677 isolate->factory()->NewReferenceError("not_defined", | 8716 isolate->factory()->NewReferenceError("not_defined", |
8678 HandleVector(&name, 1)); | 8717 HandleVector(&name, 1)); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8711 PropertyAttributes attributes; | 8750 PropertyAttributes attributes; |
8712 ContextLookupFlags flags = FOLLOW_CHAINS; | 8751 ContextLookupFlags flags = FOLLOW_CHAINS; |
8713 BindingFlags binding_flags; | 8752 BindingFlags binding_flags; |
8714 Handle<Object> holder = context->Lookup(name, | 8753 Handle<Object> holder = context->Lookup(name, |
8715 flags, | 8754 flags, |
8716 &index, | 8755 &index, |
8717 &attributes, | 8756 &attributes, |
8718 &binding_flags); | 8757 &binding_flags); |
8719 | 8758 |
8720 if (index >= 0) { | 8759 if (index >= 0) { |
8721 // The property was found in a context slot. | 8760 if (holder->IsContext()) { |
8722 Handle<Context> context = Handle<Context>::cast(holder); | 8761 Handle<Context> context = Handle<Context>::cast(holder); |
8723 if (binding_flags == MUTABLE_CHECK_INITIALIZED && | 8762 if (binding_flags == MUTABLE_CHECK_INITIALIZED && |
8724 context->get(index)->IsTheHole()) { | 8763 context->get(index)->IsTheHole()) { |
8725 Handle<Object> error = | 8764 Handle<Object> error = |
8726 isolate->factory()->NewReferenceError("not_defined", | 8765 isolate->factory()->NewReferenceError("not_defined", |
8727 HandleVector(&name, 1)); | 8766 HandleVector(&name, 1)); |
8728 return isolate->Throw(*error); | 8767 return isolate->Throw(*error); |
8729 } | 8768 } |
8730 // Ignore if read_only variable. | 8769 // Ignore if read_only variable. |
8731 if ((attributes & READ_ONLY) == 0) { | 8770 if ((attributes & READ_ONLY) == 0) { |
8732 // Context is a fixed array and set cannot fail. | 8771 // Context is a fixed array and set cannot fail. |
8733 context->set(index, *value); | 8772 context->set(index, *value); |
8734 } else if (strict_mode == kStrictMode) { | 8773 } else if (strict_mode == kStrictMode) { |
8735 // Setting read only property in strict mode. | 8774 // Setting read only property in strict mode. |
8736 Handle<Object> error = | 8775 Handle<Object> error = |
8737 isolate->factory()->NewTypeError("strict_cannot_assign", | 8776 isolate->factory()->NewTypeError("strict_cannot_assign", |
8738 HandleVector(&name, 1)); | 8777 HandleVector(&name, 1)); |
8739 return isolate->Throw(*error); | 8778 return isolate->Throw(*error); |
| 8779 } |
| 8780 } else { |
| 8781 ASSERT((attributes & READ_ONLY) == 0); |
| 8782 Handle<Object> result = |
| 8783 SetElement(Handle<JSObject>::cast(holder), index, value, strict_mode); |
| 8784 if (result.is_null()) { |
| 8785 ASSERT(isolate->has_pending_exception()); |
| 8786 return Failure::Exception(); |
| 8787 } |
8740 } | 8788 } |
8741 return *value; | 8789 return *value; |
8742 } | 8790 } |
8743 | 8791 |
8744 // Slow case: The property is not in a context slot. It is either in a | 8792 // Slow case: The property is not in a FixedArray context. |
8745 // context extension object, a property of the subject of a with, or a | 8793 // It is either in an JSObject extension context or it was not found. |
8746 // property of the global object. | 8794 Handle<JSObject> context_ext; |
8747 Handle<JSObject> object; | |
8748 | 8795 |
8749 if (!holder.is_null()) { | 8796 if (!holder.is_null()) { |
8750 // The property exists on the holder. | 8797 // The property exists in the extension context. |
8751 object = Handle<JSObject>::cast(holder); | 8798 context_ext = Handle<JSObject>::cast(holder); |
8752 } else { | 8799 } else { |
8753 // The property was not found. | 8800 // The property was not found. |
8754 ASSERT(attributes == ABSENT); | 8801 ASSERT(attributes == ABSENT); |
8755 | 8802 |
8756 if (strict_mode == kStrictMode) { | 8803 if (strict_mode == kStrictMode) { |
8757 // Throw in strict mode (assignment to undefined variable). | 8804 // Throw in strict mode (assignment to undefined variable). |
8758 Handle<Object> error = | 8805 Handle<Object> error = |
8759 isolate->factory()->NewReferenceError( | 8806 isolate->factory()->NewReferenceError( |
8760 "not_defined", HandleVector(&name, 1)); | 8807 "not_defined", HandleVector(&name, 1)); |
8761 return isolate->Throw(*error); | 8808 return isolate->Throw(*error); |
8762 } | 8809 } |
8763 // In non-strict mode, the property is added to the global object. | 8810 // In non-strict mode, the property is stored in the global context. |
8764 attributes = NONE; | 8811 attributes = NONE; |
8765 object = Handle<JSObject>(isolate->context()->global()); | 8812 context_ext = Handle<JSObject>(isolate->context()->global()); |
8766 } | 8813 } |
8767 | 8814 |
8768 // Set the property if it's not read only or doesn't yet exist. | 8815 // Set the property, but ignore if read_only variable on the context |
| 8816 // extension object itself. |
8769 if ((attributes & READ_ONLY) == 0 || | 8817 if ((attributes & READ_ONLY) == 0 || |
8770 (object->GetLocalPropertyAttribute(*name) == ABSENT)) { | 8818 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { |
8771 RETURN_IF_EMPTY_HANDLE( | 8819 RETURN_IF_EMPTY_HANDLE( |
8772 isolate, | 8820 isolate, |
8773 SetProperty(object, name, value, NONE, strict_mode)); | 8821 SetProperty(context_ext, name, value, NONE, strict_mode)); |
8774 } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) { | 8822 } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) { |
8775 // Setting read only property in strict mode. | 8823 // Setting read only property in strict mode. |
8776 Handle<Object> error = | 8824 Handle<Object> error = |
8777 isolate->factory()->NewTypeError( | 8825 isolate->factory()->NewTypeError( |
8778 "strict_cannot_assign", HandleVector(&name, 1)); | 8826 "strict_cannot_assign", HandleVector(&name, 1)); |
8779 return isolate->Throw(*error); | 8827 return isolate->Throw(*error); |
8780 } | 8828 } |
8781 return *value; | 8829 return *value; |
8782 } | 8830 } |
8783 | 8831 |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9168 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 9216 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
9169 ASSERT(Context::cast(frame->context()) == *context); | 9217 ASSERT(Context::cast(frame->context()) == *context); |
9170 #endif | 9218 #endif |
9171 | 9219 |
9172 // Find where the 'eval' symbol is bound. It is unaliased only if | 9220 // Find where the 'eval' symbol is bound. It is unaliased only if |
9173 // it is bound in the global context. | 9221 // it is bound in the global context. |
9174 int index = -1; | 9222 int index = -1; |
9175 PropertyAttributes attributes = ABSENT; | 9223 PropertyAttributes attributes = ABSENT; |
9176 BindingFlags binding_flags; | 9224 BindingFlags binding_flags; |
9177 while (true) { | 9225 while (true) { |
9178 // Don't follow context chains in Context::Lookup and implement the loop | |
9179 // up the context chain here, so that we can know the context where eval | |
9180 // was found. | |
9181 receiver = context->Lookup(isolate->factory()->eval_symbol(), | 9226 receiver = context->Lookup(isolate->factory()->eval_symbol(), |
9182 FOLLOW_PROTOTYPE_CHAIN, | 9227 FOLLOW_PROTOTYPE_CHAIN, |
9183 &index, | 9228 &index, |
9184 &attributes, | 9229 &attributes, |
9185 &binding_flags); | 9230 &binding_flags); |
9186 // Stop search when eval is found or when the global context is | 9231 // Stop search when eval is found or when the global context is |
9187 // reached. | 9232 // reached. |
9188 if (attributes != ABSENT || context->IsGlobalContext()) break; | 9233 if (attributes != ABSENT || context->IsGlobalContext()) break; |
9189 context = Handle<Context>(context->previous(), isolate); | 9234 context = Handle<Context>(context->previous(), isolate); |
9190 } | 9235 } |
(...skipping 3908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13099 } else { | 13144 } else { |
13100 // Handle last resort GC and make sure to allow future allocations | 13145 // Handle last resort GC and make sure to allow future allocations |
13101 // to grow the heap without causing GCs (if possible). | 13146 // to grow the heap without causing GCs (if possible). |
13102 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13147 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13103 isolate->heap()->CollectAllGarbage(false); | 13148 isolate->heap()->CollectAllGarbage(false); |
13104 } | 13149 } |
13105 } | 13150 } |
13106 | 13151 |
13107 | 13152 |
13108 } } // namespace v8::internal | 13153 } } // namespace v8::internal |
OLD | NEW |