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

Side by Side Diff: src/runtime.cc

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

Powered by Google App Engine
This is Rietveld 408576698