| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 cell->set_value(Heap::the_hole_value()); | 469 cell->set_value(Heap::the_hole_value()); |
| 470 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 470 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| 471 } else { | 471 } else { |
| 472 return dictionary->DeleteProperty(entry, mode); | 472 return dictionary->DeleteProperty(entry, mode); |
| 473 } | 473 } |
| 474 } | 474 } |
| 475 return Heap::true_value(); | 475 return Heap::true_value(); |
| 476 } | 476 } |
| 477 | 477 |
| 478 | 478 |
| 479 bool JSObject::IsDirty() { |
| 480 Object* cons_obj = map()->constructor(); |
| 481 if (!cons_obj->IsJSFunction()) |
| 482 return true; |
| 483 JSFunction* fun = JSFunction::cast(cons_obj); |
| 484 if (!fun->shared()->function_data()->IsFunctionTemplateInfo()) |
| 485 return true; |
| 486 // If the object is fully fast case and has the same map it was |
| 487 // created with then no changes can have been made to it. |
| 488 return map() != fun->initial_map() |
| 489 || !HasFastElements() |
| 490 || !HasFastProperties(); |
| 491 } |
| 492 |
| 493 |
| 479 Object* Object::GetProperty(Object* receiver, | 494 Object* Object::GetProperty(Object* receiver, |
| 480 LookupResult* result, | 495 LookupResult* result, |
| 481 String* name, | 496 String* name, |
| 482 PropertyAttributes* attributes) { | 497 PropertyAttributes* attributes) { |
| 483 // Make sure that the top context does not change when doing | 498 // Make sure that the top context does not change when doing |
| 484 // callbacks or interceptor calls. | 499 // callbacks or interceptor calls. |
| 485 AssertNoContextChange ncc; | 500 AssertNoContextChange ncc; |
| 486 | 501 |
| 487 // Traverse the prototype chain from the current object (this) to | 502 // Traverse the prototype chain from the current object (this) to |
| 488 // the holder and check for access rights. This avoid traversing the | 503 // the holder and check for access rights. This avoid traversing the |
| (...skipping 4444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4933 | 4948 |
| 4934 void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) { | 4949 void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) { |
| 4935 IteratePointers(v, kNameOffset, kConstructStubOffset + kPointerSize); | 4950 IteratePointers(v, kNameOffset, kConstructStubOffset + kPointerSize); |
| 4936 IteratePointers(v, kInstanceClassNameOffset, kScriptOffset + kPointerSize); | 4951 IteratePointers(v, kInstanceClassNameOffset, kScriptOffset + kPointerSize); |
| 4937 IteratePointers(v, kDebugInfoOffset, kInferredNameOffset + kPointerSize); | 4952 IteratePointers(v, kDebugInfoOffset, kInferredNameOffset + kPointerSize); |
| 4938 IteratePointers(v, kThisPropertyAssignmentsOffset, | 4953 IteratePointers(v, kThisPropertyAssignmentsOffset, |
| 4939 kThisPropertyAssignmentsOffset + kPointerSize); | 4954 kThisPropertyAssignmentsOffset + kPointerSize); |
| 4940 } | 4955 } |
| 4941 | 4956 |
| 4942 | 4957 |
| 4943 void ObjectVisitor::BeginCodeIteration(Code* code) { | |
| 4944 ASSERT(code->ic_flag() == Code::IC_TARGET_IS_OBJECT); | |
| 4945 } | |
| 4946 | |
| 4947 | |
| 4948 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) { | 4958 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) { |
| 4949 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); | 4959 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
| 4950 VisitPointer(rinfo->target_object_address()); | 4960 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 4961 Object* old_target = target; |
| 4962 VisitPointer(&target); |
| 4963 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 4951 } | 4964 } |
| 4952 | 4965 |
| 4953 | 4966 |
| 4954 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) { | 4967 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) { |
| 4955 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) && rinfo->IsCallInstruction()); | 4968 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) && rinfo->IsCallInstruction()); |
| 4956 VisitPointer(rinfo->call_object_address()); | 4969 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 4957 } | 4970 Object* old_target = target; |
| 4958 | 4971 VisitPointer(&target); |
| 4959 | 4972 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 4960 // Convert relocatable targets from address to code object address. This is | |
| 4961 // mainly IC call targets but for debugging straight-line code can be replaced | |
| 4962 // with a call instruction which also has to be relocated. | |
| 4963 void Code::ConvertICTargetsFromAddressToObject() { | |
| 4964 ASSERT(ic_flag() == IC_TARGET_IS_ADDRESS); | |
| 4965 | |
| 4966 for (RelocIterator it(this, RelocInfo::kCodeTargetMask); | |
| 4967 !it.done(); it.next()) { | |
| 4968 Address ic_addr = it.rinfo()->target_address(); | |
| 4969 ASSERT(ic_addr != NULL); | |
| 4970 HeapObject* code = Code::GetCodeFromTargetAddress(ic_addr); | |
| 4971 ASSERT(code->IsHeapObject()); | |
| 4972 it.rinfo()->set_target_object(code); | |
| 4973 } | |
| 4974 | |
| 4975 #ifdef ENABLE_DEBUGGER_SUPPORT | |
| 4976 if (Debug::has_break_points()) { | |
| 4977 for (RelocIterator it(this, RelocInfo::ModeMask(RelocInfo::JS_RETURN)); | |
| 4978 !it.done(); | |
| 4979 it.next()) { | |
| 4980 if (it.rinfo()->IsCallInstruction()) { | |
| 4981 Address addr = it.rinfo()->call_address(); | |
| 4982 ASSERT(addr != NULL); | |
| 4983 HeapObject* code = Code::GetCodeFromTargetAddress(addr); | |
| 4984 ASSERT(code->IsHeapObject()); | |
| 4985 it.rinfo()->set_call_object(code); | |
| 4986 } | |
| 4987 } | |
| 4988 } | |
| 4989 #endif | |
| 4990 set_ic_flag(IC_TARGET_IS_OBJECT); | |
| 4991 } | 4973 } |
| 4992 | 4974 |
| 4993 | 4975 |
| 4994 void Code::CodeIterateBody(ObjectVisitor* v) { | 4976 void Code::CodeIterateBody(ObjectVisitor* v) { |
| 4995 v->BeginCodeIteration(this); | |
| 4996 | |
| 4997 int mode_mask = RelocInfo::kCodeTargetMask | | 4977 int mode_mask = RelocInfo::kCodeTargetMask | |
| 4998 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 4978 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
| 4999 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 4979 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
| 5000 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | | 4980 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | |
| 5001 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | 4981 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
| 5002 | 4982 |
| 5003 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { | 4983 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { |
| 5004 RelocInfo::Mode rmode = it.rinfo()->rmode(); | 4984 RelocInfo::Mode rmode = it.rinfo()->rmode(); |
| 5005 if (rmode == RelocInfo::EMBEDDED_OBJECT) { | 4985 if (rmode == RelocInfo::EMBEDDED_OBJECT) { |
| 5006 v->VisitPointer(it.rinfo()->target_object_address()); | 4986 v->VisitPointer(it.rinfo()->target_object_address()); |
| 5007 } else if (RelocInfo::IsCodeTarget(rmode)) { | 4987 } else if (RelocInfo::IsCodeTarget(rmode)) { |
| 5008 v->VisitCodeTarget(it.rinfo()); | 4988 v->VisitCodeTarget(it.rinfo()); |
| 5009 } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) { | 4989 } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) { |
| 5010 v->VisitExternalReference(it.rinfo()->target_reference_address()); | 4990 v->VisitExternalReference(it.rinfo()->target_reference_address()); |
| 5011 #ifdef ENABLE_DEBUGGER_SUPPORT | 4991 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 5012 } else if (Debug::has_break_points() && | 4992 } else if (Debug::has_break_points() && |
| 5013 RelocInfo::IsJSReturn(rmode) && | 4993 RelocInfo::IsJSReturn(rmode) && |
| 5014 it.rinfo()->IsCallInstruction()) { | 4994 it.rinfo()->IsCallInstruction()) { |
| 5015 v->VisitDebugTarget(it.rinfo()); | 4995 v->VisitDebugTarget(it.rinfo()); |
| 5016 #endif | 4996 #endif |
| 5017 } else if (rmode == RelocInfo::RUNTIME_ENTRY) { | 4997 } else if (rmode == RelocInfo::RUNTIME_ENTRY) { |
| 5018 v->VisitRuntimeEntry(it.rinfo()); | 4998 v->VisitRuntimeEntry(it.rinfo()); |
| 5019 } | 4999 } |
| 5020 } | 5000 } |
| 5021 | 5001 |
| 5022 ScopeInfo<>::IterateScopeInfo(this, v); | 5002 ScopeInfo<>::IterateScopeInfo(this, v); |
| 5023 | |
| 5024 v->EndCodeIteration(this); | |
| 5025 } | |
| 5026 | |
| 5027 | |
| 5028 void Code::ConvertICTargetsFromObjectToAddress() { | |
| 5029 ASSERT(ic_flag() == IC_TARGET_IS_OBJECT); | |
| 5030 | |
| 5031 for (RelocIterator it(this, RelocInfo::kCodeTargetMask); | |
| 5032 !it.done(); it.next()) { | |
| 5033 // We cannot use the safe cast (Code::cast) here, because we may be in | |
| 5034 // the middle of relocating old objects during GC and the map pointer in | |
| 5035 // the code object may be mangled | |
| 5036 Code* code = reinterpret_cast<Code*>(it.rinfo()->target_object()); | |
| 5037 ASSERT((code != NULL) && code->IsHeapObject()); | |
| 5038 it.rinfo()->set_target_address(code->instruction_start()); | |
| 5039 } | |
| 5040 | |
| 5041 #ifdef ENABLE_DEBUGGER_SUPPORT | |
| 5042 if (Debug::has_break_points()) { | |
| 5043 for (RelocIterator it(this, RelocInfo::ModeMask(RelocInfo::JS_RETURN)); | |
| 5044 !it.done(); | |
| 5045 it.next()) { | |
| 5046 if (it.rinfo()->IsCallInstruction()) { | |
| 5047 Code* code = reinterpret_cast<Code*>(it.rinfo()->call_object()); | |
| 5048 ASSERT((code != NULL) && code->IsHeapObject()); | |
| 5049 it.rinfo()->set_call_address(code->instruction_start()); | |
| 5050 } | |
| 5051 } | |
| 5052 } | |
| 5053 #endif | |
| 5054 set_ic_flag(IC_TARGET_IS_ADDRESS); | |
| 5055 } | 5003 } |
| 5056 | 5004 |
| 5057 | 5005 |
| 5058 void Code::Relocate(int delta) { | 5006 void Code::Relocate(int delta) { |
| 5059 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { | 5007 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { |
| 5060 it.rinfo()->apply(delta); | 5008 it.rinfo()->apply(delta); |
| 5061 } | 5009 } |
| 5062 CPU::FlushICache(instruction_start(), instruction_size()); | 5010 CPU::FlushICache(instruction_start(), instruction_size()); |
| 5063 } | 5011 } |
| 5064 | 5012 |
| (...skipping 2950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8015 if (break_point_objects()->IsUndefined()) return 0; | 7963 if (break_point_objects()->IsUndefined()) return 0; |
| 8016 // Single beak point. | 7964 // Single beak point. |
| 8017 if (!break_point_objects()->IsFixedArray()) return 1; | 7965 if (!break_point_objects()->IsFixedArray()) return 1; |
| 8018 // Multiple break points. | 7966 // Multiple break points. |
| 8019 return FixedArray::cast(break_point_objects())->length(); | 7967 return FixedArray::cast(break_point_objects())->length(); |
| 8020 } | 7968 } |
| 8021 #endif | 7969 #endif |
| 8022 | 7970 |
| 8023 | 7971 |
| 8024 } } // namespace v8::internal | 7972 } } // namespace v8::internal |
| OLD | NEW |