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 |