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

Side by Side Diff: src/runtime.cc

Issue 7782030: 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 1284 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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