| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 12 matching lines...) Expand all Loading... |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "api.h" | 30 #include "api.h" |
| 31 #include "arguments.h" | 31 #include "arguments.h" |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "codegen.h" |
| 33 #include "debug.h" | 34 #include "debug.h" |
| 35 #include "deoptimizer.h" |
| 34 #include "execution.h" | 36 #include "execution.h" |
| 37 #include "full-codegen.h" |
| 38 #include "hydrogen.h" |
| 35 #include "objects-inl.h" | 39 #include "objects-inl.h" |
| 36 #include "objects-visiting.h" | 40 #include "objects-visiting.h" |
| 37 #include "macro-assembler.h" | 41 #include "macro-assembler.h" |
| 42 #include "safepoint-table.h" |
| 38 #include "scanner-base.h" | 43 #include "scanner-base.h" |
| 39 #include "scopeinfo.h" | 44 #include "scopeinfo.h" |
| 40 #include "string-stream.h" | 45 #include "string-stream.h" |
| 41 #include "utils.h" | 46 #include "utils.h" |
| 47 #include "vm-state-inl.h" |
| 42 | 48 |
| 43 #ifdef ENABLE_DISASSEMBLER | 49 #ifdef ENABLE_DISASSEMBLER |
| 50 #include "disasm.h" |
| 44 #include "disassembler.h" | 51 #include "disassembler.h" |
| 45 #endif | 52 #endif |
| 46 | 53 |
| 47 namespace v8 { | 54 namespace v8 { |
| 48 namespace internal { | 55 namespace internal { |
| 49 | 56 |
| 50 // Getters and setters are stored in a fixed array property. These are | 57 // Getters and setters are stored in a fixed array property. These are |
| 51 // constants for their indices. | 58 // constants for their indices. |
| 52 const int kGetterIndex = 0; | 59 const int kGetterIndex = 0; |
| 53 const int kSetterIndex = 1; | 60 const int kSetterIndex = 1; |
| (...skipping 1705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1759 DescriptorArray* descriptors = map()->instance_descriptors(); | 1766 DescriptorArray* descriptors = map()->instance_descriptors(); |
| 1760 int number = descriptors->SearchWithCache(name); | 1767 int number = descriptors->SearchWithCache(name); |
| 1761 if (number != DescriptorArray::kNotFound) { | 1768 if (number != DescriptorArray::kNotFound) { |
| 1762 result->DescriptorResult(this, descriptors->GetDetails(number), number); | 1769 result->DescriptorResult(this, descriptors->GetDetails(number), number); |
| 1763 } else { | 1770 } else { |
| 1764 result->NotFound(); | 1771 result->NotFound(); |
| 1765 } | 1772 } |
| 1766 } | 1773 } |
| 1767 | 1774 |
| 1768 | 1775 |
| 1776 void Map::LookupInDescriptors(JSObject* holder, |
| 1777 String* name, |
| 1778 LookupResult* result) { |
| 1779 DescriptorArray* descriptors = instance_descriptors(); |
| 1780 DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache(); |
| 1781 int number = cache->Lookup(descriptors, name); |
| 1782 if (number == DescriptorLookupCache::kAbsent) { |
| 1783 number = descriptors->Search(name); |
| 1784 cache->Update(descriptors, name, number); |
| 1785 } |
| 1786 if (number != DescriptorArray::kNotFound) { |
| 1787 result->DescriptorResult(holder, descriptors->GetDetails(number), number); |
| 1788 } else { |
| 1789 result->NotFound(); |
| 1790 } |
| 1791 } |
| 1792 |
| 1793 |
| 1769 void JSObject::LocalLookupRealNamedProperty(String* name, | 1794 void JSObject::LocalLookupRealNamedProperty(String* name, |
| 1770 LookupResult* result) { | 1795 LookupResult* result) { |
| 1771 if (IsJSGlobalProxy()) { | 1796 if (IsJSGlobalProxy()) { |
| 1772 Object* proto = GetPrototype(); | 1797 Object* proto = GetPrototype(); |
| 1773 if (proto->IsNull()) return result->NotFound(); | 1798 if (proto->IsNull()) return result->NotFound(); |
| 1774 ASSERT(proto->IsJSGlobalObject()); | 1799 ASSERT(proto->IsJSGlobalObject()); |
| 1775 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); | 1800 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); |
| 1776 } | 1801 } |
| 1777 | 1802 |
| 1778 if (HasFastProperties()) { | 1803 if (HasFastProperties()) { |
| (...skipping 1331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3110 } | 3135 } |
| 3111 | 3136 |
| 3112 // For the global object allocate a new map to invalidate the global inline | 3137 // For the global object allocate a new map to invalidate the global inline |
| 3113 // caches which have a global property cell reference directly in the code. | 3138 // caches which have a global property cell reference directly in the code. |
| 3114 if (IsGlobalObject()) { | 3139 if (IsGlobalObject()) { |
| 3115 Object* new_map; | 3140 Object* new_map; |
| 3116 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | 3141 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
| 3117 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 3142 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 3118 } | 3143 } |
| 3119 set_map(Map::cast(new_map)); | 3144 set_map(Map::cast(new_map)); |
| 3145 // When running crankshaft, changing the map is not enough. We |
| 3146 // need to deoptimize all functions that rely on this global |
| 3147 // object. |
| 3148 Deoptimizer::DeoptimizeGlobalObject(this); |
| 3120 } | 3149 } |
| 3121 | 3150 |
| 3122 // Update the dictionary with the new CALLBACKS property. | 3151 // Update the dictionary with the new CALLBACKS property. |
| 3123 Object* result; | 3152 Object* result; |
| 3124 { MaybeObject* maybe_result = SetNormalizedProperty(name, structure, details); | 3153 { MaybeObject* maybe_result = SetNormalizedProperty(name, structure, details); |
| 3125 if (!maybe_result->ToObject(&result)) return maybe_result; | 3154 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3126 } | 3155 } |
| 3127 | 3156 |
| 3128 if (convert_back_to_fast) { | 3157 if (convert_back_to_fast) { |
| 3129 { MaybeObject* maybe_ok = TransformToFastProperties(0); | 3158 { MaybeObject* maybe_ok = TransformToFastProperties(0); |
| (...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4196 if ((entry->Hash() == hash) && | 4225 if ((entry->Hash() == hash) && |
| 4197 name->Equals(entry) && | 4226 name->Equals(entry) && |
| 4198 !is_null_descriptor(number)) { | 4227 !is_null_descriptor(number)) { |
| 4199 return number; | 4228 return number; |
| 4200 } | 4229 } |
| 4201 } | 4230 } |
| 4202 return kNotFound; | 4231 return kNotFound; |
| 4203 } | 4232 } |
| 4204 | 4233 |
| 4205 | 4234 |
| 4235 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count, |
| 4236 PretenureFlag pretenure) { |
| 4237 ASSERT(deopt_entry_count > 0); |
| 4238 return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count), |
| 4239 pretenure); |
| 4240 } |
| 4241 |
| 4242 |
| 4243 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points, |
| 4244 PretenureFlag pretenure) { |
| 4245 if (number_of_deopt_points == 0) return HEAP->empty_fixed_array(); |
| 4246 return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points), |
| 4247 pretenure); |
| 4248 } |
| 4249 |
| 4250 |
| 4206 #ifdef DEBUG | 4251 #ifdef DEBUG |
| 4207 bool DescriptorArray::IsEqualTo(DescriptorArray* other) { | 4252 bool DescriptorArray::IsEqualTo(DescriptorArray* other) { |
| 4208 if (IsEmpty()) return other->IsEmpty(); | 4253 if (IsEmpty()) return other->IsEmpty(); |
| 4209 if (other->IsEmpty()) return false; | 4254 if (other->IsEmpty()) return false; |
| 4210 if (length() != other->length()) return false; | 4255 if (length() != other->length()) return false; |
| 4211 for (int i = 0; i < length(); ++i) { | 4256 for (int i = 0; i < length(); ++i) { |
| 4212 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; | 4257 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; |
| 4213 } | 4258 } |
| 4214 return GetContentArray()->IsEqualTo(other->GetContentArray()); | 4259 return GetContentArray()->IsEqualTo(other->GetContentArray()); |
| 4215 } | 4260 } |
| 4216 #endif | 4261 #endif |
| 4217 | 4262 |
| 4218 | 4263 |
| 4219 bool String::LooksValid() { | 4264 bool String::LooksValid() { |
| 4220 if (!GetHeap()->Contains(this)) return false; | 4265 if (!Isolate::Current()->heap()->Contains(this)) return false; |
| 4221 return true; | 4266 return true; |
| 4222 } | 4267 } |
| 4223 | 4268 |
| 4224 | 4269 |
| 4225 int String::Utf8Length() { | 4270 int String::Utf8Length() { |
| 4226 if (IsAsciiRepresentation()) return length(); | 4271 if (IsAsciiRepresentation()) return length(); |
| 4227 // Attempt to flatten before accessing the string. It probably | 4272 // Attempt to flatten before accessing the string. It probably |
| 4228 // doesn't make Utf8Length faster, but it is very likely that | 4273 // doesn't make Utf8Length faster, but it is very likely that |
| 4229 // the string will be accessed later (for example by WriteUtf8) | 4274 // the string will be accessed later (for example by WriteUtf8) |
| 4230 // so it's still a good idea. | 4275 // so it's still a good idea. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4291 return Vector<const uc16>(start + offset, length); | 4336 return Vector<const uc16>(start + offset, length); |
| 4292 } | 4337 } |
| 4293 | 4338 |
| 4294 | 4339 |
| 4295 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, | 4340 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, |
| 4296 RobustnessFlag robust_flag, | 4341 RobustnessFlag robust_flag, |
| 4297 int offset, | 4342 int offset, |
| 4298 int length, | 4343 int length, |
| 4299 int* length_return) { | 4344 int* length_return) { |
| 4300 ASSERT(NativeAllocationChecker::allocation_allowed()); | 4345 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 4301 Heap* heap = GetHeap(); | |
| 4302 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 4346 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 4303 return SmartPointer<char>(NULL); | 4347 return SmartPointer<char>(NULL); |
| 4304 } | 4348 } |
| 4349 Heap* heap = GetHeap(); |
| 4305 | 4350 |
| 4306 // Negative length means the to the end of the string. | 4351 // Negative length means the to the end of the string. |
| 4307 if (length < 0) length = kMaxInt - offset; | 4352 if (length < 0) length = kMaxInt - offset; |
| 4308 | 4353 |
| 4309 // Compute the size of the UTF-8 string. Start at the specified offset. | 4354 // Compute the size of the UTF-8 string. Start at the specified offset. |
| 4310 Access<StringInputBuffer> buffer( | 4355 Access<StringInputBuffer> buffer( |
| 4311 heap->isolate()->objects_string_input_buffer()); | 4356 heap->isolate()->objects_string_input_buffer()); |
| 4312 buffer->Reset(offset, this); | 4357 buffer->Reset(offset, this); |
| 4313 int character_position = offset; | 4358 int character_position = offset; |
| 4314 int utf8_bytes = 0; | 4359 int utf8_bytes = 0; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4370 case kConsStringTag: | 4415 case kConsStringTag: |
| 4371 UNREACHABLE(); | 4416 UNREACHABLE(); |
| 4372 return NULL; | 4417 return NULL; |
| 4373 } | 4418 } |
| 4374 UNREACHABLE(); | 4419 UNREACHABLE(); |
| 4375 return NULL; | 4420 return NULL; |
| 4376 } | 4421 } |
| 4377 | 4422 |
| 4378 | 4423 |
| 4379 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { | 4424 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { |
| 4380 Heap* heap = GetHeap(); | |
| 4381 ASSERT(NativeAllocationChecker::allocation_allowed()); | 4425 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 4382 | |
| 4383 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 4426 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 4384 return SmartPointer<uc16>(); | 4427 return SmartPointer<uc16>(); |
| 4385 } | 4428 } |
| 4429 Heap* heap = GetHeap(); |
| 4386 | 4430 |
| 4387 Access<StringInputBuffer> buffer( | 4431 Access<StringInputBuffer> buffer( |
| 4388 heap->isolate()->objects_string_input_buffer()); | 4432 heap->isolate()->objects_string_input_buffer()); |
| 4389 buffer->Reset(this); | 4433 buffer->Reset(this); |
| 4390 | 4434 |
| 4391 uc16* result = NewArray<uc16>(length() + 1); | 4435 uc16* result = NewArray<uc16>(length() + 1); |
| 4392 | 4436 |
| 4393 int i = 0; | 4437 int i = 0; |
| 4394 while (buffer->has_more()) { | 4438 while (buffer->has_more()) { |
| 4395 uint16_t character = buffer->GetNext(); | 4439 uint16_t character = buffer->GetNext(); |
| (...skipping 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5416 | 5460 |
| 5417 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { | 5461 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { |
| 5418 // Iterate over all fields in the body but take care in dealing with | 5462 // Iterate over all fields in the body but take care in dealing with |
| 5419 // the code entry. | 5463 // the code entry. |
| 5420 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 5464 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
| 5421 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 5465 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
| 5422 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 5466 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
| 5423 } | 5467 } |
| 5424 | 5468 |
| 5425 | 5469 |
| 5470 void JSFunction::MarkForLazyRecompilation() { |
| 5471 ASSERT(is_compiled() && !IsOptimized()); |
| 5472 ASSERT(shared()->allows_lazy_compilation()); |
| 5473 Builtins* builtins = GetIsolate()->builtins(); |
| 5474 ReplaceCode(builtins->builtin(Builtins::LazyRecompile)); |
| 5475 } |
| 5476 |
| 5477 |
| 5478 uint32_t JSFunction::SourceHash() { |
| 5479 uint32_t hash = 0; |
| 5480 Object* script = shared()->script(); |
| 5481 if (!script->IsUndefined()) { |
| 5482 Object* source = Script::cast(script)->source(); |
| 5483 if (source->IsUndefined()) hash = String::cast(source)->Hash(); |
| 5484 } |
| 5485 hash ^= ComputeIntegerHash(shared()->start_position_and_type()); |
| 5486 hash += ComputeIntegerHash(shared()->end_position()); |
| 5487 return hash; |
| 5488 } |
| 5489 |
| 5490 |
| 5491 bool JSFunction::IsInlineable() { |
| 5492 if (IsBuiltin()) return false; |
| 5493 // Check that the function has a script associated with it. |
| 5494 if (!shared()->script()->IsScript()) return false; |
| 5495 Code* code = shared()->code(); |
| 5496 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
| 5497 // If we never ran this (unlikely) then lets try to optimize it. |
| 5498 if (code->kind() != Code::FUNCTION) return true; |
| 5499 return code->optimizable(); |
| 5500 } |
| 5501 |
| 5502 |
| 5426 Object* JSFunction::SetInstancePrototype(Object* value) { | 5503 Object* JSFunction::SetInstancePrototype(Object* value) { |
| 5427 ASSERT(value->IsJSObject()); | 5504 ASSERT(value->IsJSObject()); |
| 5428 Heap* heap = GetHeap(); | 5505 Heap* heap = GetHeap(); |
| 5429 if (has_initial_map()) { | 5506 if (has_initial_map()) { |
| 5430 initial_map()->set_prototype(value); | 5507 initial_map()->set_prototype(value); |
| 5431 } else { | 5508 } else { |
| 5432 // Put the value in the initial map field until an initial map is | 5509 // Put the value in the initial map field until an initial map is |
| 5433 // needed. At that point, a new initial map is created and the | 5510 // needed. At that point, a new initial map is created and the |
| 5434 // prototype is put into the initial map where it belongs. | 5511 // prototype is put into the initial map where it belongs. |
| 5435 set_prototype_or_initial_map(value); | 5512 set_prototype_or_initial_map(value); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5478 return this; | 5555 return this; |
| 5479 } | 5556 } |
| 5480 | 5557 |
| 5481 | 5558 |
| 5482 Object* JSFunction::SetInstanceClassName(String* name) { | 5559 Object* JSFunction::SetInstanceClassName(String* name) { |
| 5483 shared()->set_instance_class_name(name); | 5560 shared()->set_instance_class_name(name); |
| 5484 return this; | 5561 return this; |
| 5485 } | 5562 } |
| 5486 | 5563 |
| 5487 | 5564 |
| 5565 void JSFunction::PrintName() { |
| 5566 SmartPointer<char> name = shared()->DebugName()->ToCString(); |
| 5567 PrintF("%s", *name); |
| 5568 } |
| 5569 |
| 5570 |
| 5488 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) { | 5571 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) { |
| 5489 return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex)); | 5572 return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex)); |
| 5490 } | 5573 } |
| 5491 | 5574 |
| 5492 | 5575 |
| 5493 MaybeObject* Oddball::Initialize(const char* to_string, | 5576 MaybeObject* Oddball::Initialize(const char* to_string, |
| 5494 Object* to_number, | 5577 Object* to_number, |
| 5495 byte kind) { | 5578 byte kind) { |
| 5496 Object* symbol; | 5579 Object* symbol; |
| 5497 { MaybeObject* maybe_symbol = | 5580 { MaybeObject* maybe_symbol = |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5512 } | 5595 } |
| 5513 | 5596 |
| 5514 | 5597 |
| 5515 bool SharedFunctionInfo::HasSourceCode() { | 5598 bool SharedFunctionInfo::HasSourceCode() { |
| 5516 return !script()->IsUndefined() && | 5599 return !script()->IsUndefined() && |
| 5517 !reinterpret_cast<Script*>(script())->source()->IsUndefined(); | 5600 !reinterpret_cast<Script*>(script())->source()->IsUndefined(); |
| 5518 } | 5601 } |
| 5519 | 5602 |
| 5520 | 5603 |
| 5521 Object* SharedFunctionInfo::GetSourceCode() { | 5604 Object* SharedFunctionInfo::GetSourceCode() { |
| 5522 Heap* heap = GetHeap(); | 5605 Isolate* isolate = GetIsolate(); |
| 5523 HandleScope scope; | 5606 if (!HasSourceCode()) return isolate->heap()->undefined_value(); |
| 5524 if (script()->IsUndefined()) return heap->undefined_value(); | 5607 HandleScope scope(isolate); |
| 5525 Object* source = Script::cast(script())->source(); | 5608 Object* source = Script::cast(script())->source(); |
| 5526 if (source->IsUndefined()) return heap->undefined_value(); | 5609 return *SubString(Handle<String>(String::cast(source), isolate), |
| 5527 return *SubString(Handle<String>(String::cast(source)), | |
| 5528 start_position(), end_position()); | 5610 start_position(), end_position()); |
| 5529 } | 5611 } |
| 5530 | 5612 |
| 5531 | 5613 |
| 5614 int SharedFunctionInfo::SourceSize() { |
| 5615 return end_position() - start_position(); |
| 5616 } |
| 5617 |
| 5618 |
| 5532 int SharedFunctionInfo::CalculateInstanceSize() { | 5619 int SharedFunctionInfo::CalculateInstanceSize() { |
| 5533 int instance_size = | 5620 int instance_size = |
| 5534 JSObject::kHeaderSize + | 5621 JSObject::kHeaderSize + |
| 5535 expected_nof_properties() * kPointerSize; | 5622 expected_nof_properties() * kPointerSize; |
| 5536 if (instance_size > JSObject::kMaxInstanceSize) { | 5623 if (instance_size > JSObject::kMaxInstanceSize) { |
| 5537 instance_size = JSObject::kMaxInstanceSize; | 5624 instance_size = JSObject::kMaxInstanceSize; |
| 5538 } | 5625 } |
| 5539 return instance_size; | 5626 return instance_size; |
| 5540 } | 5627 } |
| 5541 | 5628 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5642 FixedArray::cast(this_property_assignments())->get(index * 3 + 2); | 5729 FixedArray::cast(this_property_assignments())->get(index * 3 + 2); |
| 5643 return obj; | 5730 return obj; |
| 5644 } | 5731 } |
| 5645 | 5732 |
| 5646 | 5733 |
| 5647 // Support function for printing the source code to a StringStream | 5734 // Support function for printing the source code to a StringStream |
| 5648 // without any allocation in the heap. | 5735 // without any allocation in the heap. |
| 5649 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator, | 5736 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator, |
| 5650 int max_length) { | 5737 int max_length) { |
| 5651 // For some native functions there is no source. | 5738 // For some native functions there is no source. |
| 5652 if (script()->IsUndefined() || | 5739 if (!HasSourceCode()) { |
| 5653 Script::cast(script())->source()->IsUndefined()) { | |
| 5654 accumulator->Add("<No Source>"); | 5740 accumulator->Add("<No Source>"); |
| 5655 return; | 5741 return; |
| 5656 } | 5742 } |
| 5657 | 5743 |
| 5658 // Get the source for the script which this function came from. | 5744 // Get the source for the script which this function came from. |
| 5659 // Don't use String::cast because we don't want more assertion errors while | 5745 // Don't use String::cast because we don't want more assertion errors while |
| 5660 // we are already creating a stack dump. | 5746 // we are already creating a stack dump. |
| 5661 String* script_source = | 5747 String* script_source = |
| 5662 reinterpret_cast<String*>(Script::cast(script())->source()); | 5748 reinterpret_cast<String*>(Script::cast(script())->source()); |
| 5663 | 5749 |
| 5664 if (!script_source->LooksValid()) { | 5750 if (!script_source->LooksValid()) { |
| 5665 accumulator->Add("<Invalid Source>"); | 5751 accumulator->Add("<Invalid Source>"); |
| 5666 return; | 5752 return; |
| 5667 } | 5753 } |
| 5668 | 5754 |
| 5669 if (!is_toplevel()) { | 5755 if (!is_toplevel()) { |
| 5670 accumulator->Add("function "); | 5756 accumulator->Add("function "); |
| 5671 Object* name = this->name(); | 5757 Object* name = this->name(); |
| 5672 if (name->IsString() && String::cast(name)->length() > 0) { | 5758 if (name->IsString() && String::cast(name)->length() > 0) { |
| 5673 accumulator->PrintName(name); | 5759 accumulator->PrintName(name); |
| 5674 } | 5760 } |
| 5675 } | 5761 } |
| 5676 | 5762 |
| 5677 int len = end_position() - start_position(); | 5763 int len = end_position() - start_position(); |
| 5678 if (len > max_length) { | 5764 if (len <= max_length || max_length < 0) { |
| 5765 accumulator->Put(script_source, start_position(), end_position()); |
| 5766 } else { |
| 5679 accumulator->Put(script_source, | 5767 accumulator->Put(script_source, |
| 5680 start_position(), | 5768 start_position(), |
| 5681 start_position() + max_length); | 5769 start_position() + max_length); |
| 5682 accumulator->Add("...\n"); | 5770 accumulator->Add("...\n"); |
| 5683 } else { | |
| 5684 accumulator->Put(script_source, start_position(), end_position()); | |
| 5685 } | 5771 } |
| 5686 } | 5772 } |
| 5687 | 5773 |
| 5688 | 5774 |
| 5775 static bool IsCodeEquivalent(Code* code, Code* recompiled) { |
| 5776 if (code->instruction_size() != recompiled->instruction_size()) return false; |
| 5777 ByteArray* code_relocation = code->relocation_info(); |
| 5778 ByteArray* recompiled_relocation = recompiled->relocation_info(); |
| 5779 int length = code_relocation->length(); |
| 5780 if (length != recompiled_relocation->length()) return false; |
| 5781 int compare = memcmp(code_relocation->GetDataStartAddress(), |
| 5782 recompiled_relocation->GetDataStartAddress(), |
| 5783 length); |
| 5784 return compare == 0; |
| 5785 } |
| 5786 |
| 5787 |
| 5788 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) { |
| 5789 ASSERT(!has_deoptimization_support()); |
| 5790 AssertNoAllocation no_allocation; |
| 5791 Code* code = this->code(); |
| 5792 if (IsCodeEquivalent(code, recompiled)) { |
| 5793 // Copy the deoptimization data from the recompiled code. |
| 5794 code->set_deoptimization_data(recompiled->deoptimization_data()); |
| 5795 code->set_has_deoptimization_support(true); |
| 5796 } else { |
| 5797 // TODO(3025757): In case the recompiled isn't equivalent to the |
| 5798 // old code, we have to replace it. We should try to avoid this |
| 5799 // altogether because it flushes valuable type feedback by |
| 5800 // effectively resetting all IC state. |
| 5801 set_code(recompiled); |
| 5802 } |
| 5803 ASSERT(has_deoptimization_support()); |
| 5804 } |
| 5805 |
| 5806 |
| 5807 bool SharedFunctionInfo::VerifyBailoutId(int id) { |
| 5808 // TODO(srdjan): debugging ARM crashes in hydrogen. OK to disable while |
| 5809 // we are always bailing out on ARM. |
| 5810 |
| 5811 ASSERT(id != AstNode::kNoNumber); |
| 5812 Code* unoptimized = code(); |
| 5813 DeoptimizationOutputData* data = |
| 5814 DeoptimizationOutputData::cast(unoptimized->deoptimization_data()); |
| 5815 unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this); |
| 5816 USE(ignore); |
| 5817 return true; // Return true if there was no ASSERT. |
| 5818 } |
| 5819 |
| 5820 |
| 5689 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) { | 5821 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) { |
| 5690 ASSERT(!IsInobjectSlackTrackingInProgress()); | 5822 ASSERT(!IsInobjectSlackTrackingInProgress()); |
| 5691 | 5823 |
| 5692 // Only initiate the tracking the first time. | 5824 // Only initiate the tracking the first time. |
| 5693 if (live_objects_may_exist()) return; | 5825 if (live_objects_may_exist()) return; |
| 5694 set_live_objects_may_exist(true); | 5826 set_live_objects_may_exist(true); |
| 5695 | 5827 |
| 5696 // No tracking during the snapshot construction phase. | 5828 // No tracking during the snapshot construction phase. |
| 5697 if (Serializer::enabled()) return; | 5829 if (Serializer::enabled()) return; |
| 5698 | 5830 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5804 void ObjectVisitor::VisitCodeEntry(Address entry_address) { | 5936 void ObjectVisitor::VisitCodeEntry(Address entry_address) { |
| 5805 Object* code = Code::GetObjectFromEntryAddress(entry_address); | 5937 Object* code = Code::GetObjectFromEntryAddress(entry_address); |
| 5806 Object* old_code = code; | 5938 Object* old_code = code; |
| 5807 VisitPointer(&code); | 5939 VisitPointer(&code); |
| 5808 if (code != old_code) { | 5940 if (code != old_code) { |
| 5809 Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry(); | 5941 Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry(); |
| 5810 } | 5942 } |
| 5811 } | 5943 } |
| 5812 | 5944 |
| 5813 | 5945 |
| 5946 void ObjectVisitor::VisitGlobalPropertyCell(RelocInfo* rinfo) { |
| 5947 ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL); |
| 5948 Object* cell = rinfo->target_cell(); |
| 5949 Object* old_cell = cell; |
| 5950 VisitPointer(&cell); |
| 5951 if (cell != old_cell) { |
| 5952 rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell)); |
| 5953 } |
| 5954 } |
| 5955 |
| 5956 |
| 5814 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) { | 5957 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) { |
| 5815 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && | 5958 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && |
| 5816 rinfo->IsPatchedReturnSequence()) || | 5959 rinfo->IsPatchedReturnSequence()) || |
| 5817 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 5960 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 5818 rinfo->IsPatchedDebugBreakSlotSequence())); | 5961 rinfo->IsPatchedDebugBreakSlotSequence())); |
| 5819 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 5962 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 5820 Object* old_target = target; | 5963 Object* old_target = target; |
| 5821 VisitPointer(&target); | 5964 VisitPointer(&target); |
| 5822 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. | 5965 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 5823 } | 5966 } |
| 5824 | 5967 |
| 5825 | 5968 |
| 5969 void Code::InvalidateRelocation() { |
| 5970 set_relocation_info(GetHeap()->empty_byte_array()); |
| 5971 } |
| 5972 |
| 5973 |
| 5826 void Code::Relocate(intptr_t delta) { | 5974 void Code::Relocate(intptr_t delta) { |
| 5827 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { | 5975 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { |
| 5828 it.rinfo()->apply(delta); | 5976 it.rinfo()->apply(delta); |
| 5829 } | 5977 } |
| 5830 CPU::FlushICache(instruction_start(), instruction_size()); | 5978 CPU::FlushICache(instruction_start(), instruction_size()); |
| 5831 } | 5979 } |
| 5832 | 5980 |
| 5833 | 5981 |
| 5834 void Code::CopyFrom(const CodeDesc& desc) { | 5982 void Code::CopyFrom(const CodeDesc& desc) { |
| 5835 // copy code | 5983 // copy code |
| 5836 memmove(instruction_start(), desc.buffer, desc.instr_size); | 5984 memmove(instruction_start(), desc.buffer, desc.instr_size); |
| 5837 | 5985 |
| 5838 // copy reloc info | 5986 // copy reloc info |
| 5839 memmove(relocation_start(), | 5987 memmove(relocation_start(), |
| 5840 desc.buffer + desc.buffer_size - desc.reloc_size, | 5988 desc.buffer + desc.buffer_size - desc.reloc_size, |
| 5841 desc.reloc_size); | 5989 desc.reloc_size); |
| 5842 | 5990 |
| 5843 // unbox handles and relocate | 5991 // unbox handles and relocate |
| 5844 intptr_t delta = instruction_start() - desc.buffer; | 5992 intptr_t delta = instruction_start() - desc.buffer; |
| 5845 int mode_mask = RelocInfo::kCodeTargetMask | | 5993 int mode_mask = RelocInfo::kCodeTargetMask | |
| 5846 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 5994 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
| 5995 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | |
| 5847 RelocInfo::kApplyMask; | 5996 RelocInfo::kApplyMask; |
| 5848 Assembler* origin = desc.origin; // Needed to find target_object on X64. | 5997 Assembler* origin = desc.origin; // Needed to find target_object on X64. |
| 5849 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { | 5998 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { |
| 5850 RelocInfo::Mode mode = it.rinfo()->rmode(); | 5999 RelocInfo::Mode mode = it.rinfo()->rmode(); |
| 5851 if (mode == RelocInfo::EMBEDDED_OBJECT) { | 6000 if (mode == RelocInfo::EMBEDDED_OBJECT) { |
| 5852 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 6001 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 5853 it.rinfo()->set_target_object(*p); | 6002 it.rinfo()->set_target_object(*p); |
| 6003 } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { |
| 6004 Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle(); |
| 6005 it.rinfo()->set_target_cell(*cell); |
| 5854 } else if (RelocInfo::IsCodeTarget(mode)) { | 6006 } else if (RelocInfo::IsCodeTarget(mode)) { |
| 5855 // rewrite code handles in inline cache targets to direct | 6007 // rewrite code handles in inline cache targets to direct |
| 5856 // pointers to the first instruction in the code object | 6008 // pointers to the first instruction in the code object |
| 5857 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 6009 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 5858 Code* code = Code::cast(*p); | 6010 Code* code = Code::cast(*p); |
| 5859 it.rinfo()->set_target_address(code->instruction_start()); | 6011 it.rinfo()->set_target_address(code->instruction_start()); |
| 5860 } else { | 6012 } else { |
| 5861 it.rinfo()->apply(delta); | 6013 it.rinfo()->apply(delta); |
| 5862 } | 6014 } |
| 5863 } | 6015 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5914 if (statement_position < p && p <= position) { | 6066 if (statement_position < p && p <= position) { |
| 5915 statement_position = p; | 6067 statement_position = p; |
| 5916 } | 6068 } |
| 5917 } | 6069 } |
| 5918 it.next(); | 6070 it.next(); |
| 5919 } | 6071 } |
| 5920 return statement_position; | 6072 return statement_position; |
| 5921 } | 6073 } |
| 5922 | 6074 |
| 5923 | 6075 |
| 6076 uint8_t* Code::GetSafepointEntry(Address pc) { |
| 6077 SafepointTable table(this); |
| 6078 unsigned pc_offset = pc - instruction_start(); |
| 6079 for (unsigned i = 0; i < table.length(); i++) { |
| 6080 // TODO(kasperl): Replace the linear search with binary search. |
| 6081 if (table.GetPcOffset(i) == pc_offset) return table.GetEntry(i); |
| 6082 } |
| 6083 return NULL; |
| 6084 } |
| 6085 |
| 6086 |
| 6087 void Code::SetNoStackCheckTable() { |
| 6088 // Indicate the absence of a stack-check table by a table start after the |
| 6089 // end of the instructions. Table start must be aligned, so round up. |
| 6090 set_stack_check_table_start(RoundUp(instruction_size(), kIntSize)); |
| 6091 } |
| 6092 |
| 6093 |
| 6094 Map* Code::FindFirstMap() { |
| 6095 ASSERT(is_inline_cache_stub()); |
| 6096 AssertNoAllocation no_allocation; |
| 6097 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 6098 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 6099 RelocInfo* info = it.rinfo(); |
| 6100 Object* object = info->target_object(); |
| 6101 if (object->IsMap()) return Map::cast(object); |
| 6102 } |
| 6103 return NULL; |
| 6104 } |
| 6105 |
| 6106 |
| 5924 #ifdef ENABLE_DISASSEMBLER | 6107 #ifdef ENABLE_DISASSEMBLER |
| 6108 |
| 6109 #ifdef DEBUG |
| 6110 |
| 6111 void DeoptimizationInputData::DeoptimizationInputDataPrint() { |
| 6112 disasm::NameConverter converter; |
| 6113 int deopt_count = DeoptCount(); |
| 6114 PrintF("Deoptimization Input Data (deopt points = %d)\n", deopt_count); |
| 6115 if (0 == deopt_count) return; |
| 6116 |
| 6117 PrintF("%6s %6s %6s %12s\n", "index", "ast id", "argc", "commands"); |
| 6118 for (int i = 0; i < deopt_count; i++) { |
| 6119 int command_count = 0; |
| 6120 PrintF("%6d %6d %6d", |
| 6121 i, AstId(i)->value(), ArgumentsStackHeight(i)->value()); |
| 6122 int translation_index = TranslationIndex(i)->value(); |
| 6123 TranslationIterator iterator(TranslationByteArray(), translation_index); |
| 6124 Translation::Opcode opcode = |
| 6125 static_cast<Translation::Opcode>(iterator.Next()); |
| 6126 ASSERT(Translation::BEGIN == opcode); |
| 6127 int frame_count = iterator.Next(); |
| 6128 if (FLAG_print_code_verbose) { |
| 6129 PrintF(" %s {count=%d}\n", Translation::StringFor(opcode), frame_count); |
| 6130 } |
| 6131 |
| 6132 for (int i = 0; i < frame_count; ++i) { |
| 6133 opcode = static_cast<Translation::Opcode>(iterator.Next()); |
| 6134 ASSERT(Translation::FRAME == opcode); |
| 6135 int ast_id = iterator.Next(); |
| 6136 int function_id = iterator.Next(); |
| 6137 JSFunction* function = |
| 6138 JSFunction::cast(LiteralArray()->get(function_id)); |
| 6139 unsigned height = iterator.Next(); |
| 6140 if (FLAG_print_code_verbose) { |
| 6141 PrintF("%24s %s {ast_id=%d, function=", |
| 6142 "", Translation::StringFor(opcode), ast_id); |
| 6143 function->PrintName(); |
| 6144 PrintF(", height=%u}\n", height); |
| 6145 } |
| 6146 |
| 6147 // Size of translation is height plus all incoming arguments including |
| 6148 // receiver. |
| 6149 int size = height + function->shared()->formal_parameter_count() + 1; |
| 6150 command_count += size; |
| 6151 for (int j = 0; j < size; ++j) { |
| 6152 opcode = static_cast<Translation::Opcode>(iterator.Next()); |
| 6153 if (FLAG_print_code_verbose) { |
| 6154 PrintF("%24s %s ", "", Translation::StringFor(opcode)); |
| 6155 } |
| 6156 |
| 6157 if (opcode == Translation::DUPLICATE) { |
| 6158 opcode = static_cast<Translation::Opcode>(iterator.Next()); |
| 6159 if (FLAG_print_code_verbose) { |
| 6160 PrintF("%s ", Translation::StringFor(opcode)); |
| 6161 } |
| 6162 --j; // Two commands share the same frame index. |
| 6163 } |
| 6164 |
| 6165 switch (opcode) { |
| 6166 case Translation::BEGIN: |
| 6167 case Translation::FRAME: |
| 6168 case Translation::DUPLICATE: |
| 6169 UNREACHABLE(); |
| 6170 break; |
| 6171 |
| 6172 case Translation::REGISTER: { |
| 6173 int reg_code = iterator.Next(); |
| 6174 if (FLAG_print_code_verbose) { |
| 6175 PrintF("{input=%s}", converter.NameOfCPURegister(reg_code)); |
| 6176 } |
| 6177 break; |
| 6178 } |
| 6179 |
| 6180 case Translation::INT32_REGISTER: { |
| 6181 int reg_code = iterator.Next(); |
| 6182 if (FLAG_print_code_verbose) { |
| 6183 PrintF("{input=%s}", converter.NameOfCPURegister(reg_code)); |
| 6184 } |
| 6185 break; |
| 6186 } |
| 6187 |
| 6188 case Translation::DOUBLE_REGISTER: { |
| 6189 int reg_code = iterator.Next(); |
| 6190 if (FLAG_print_code_verbose) { |
| 6191 PrintF("{input=%s}", |
| 6192 DoubleRegister::AllocationIndexToString(reg_code)); |
| 6193 } |
| 6194 break; |
| 6195 } |
| 6196 |
| 6197 case Translation::STACK_SLOT: { |
| 6198 int input_slot_index = iterator.Next(); |
| 6199 if (FLAG_print_code_verbose) { |
| 6200 PrintF("{input=%d}", input_slot_index); |
| 6201 } |
| 6202 break; |
| 6203 } |
| 6204 |
| 6205 case Translation::INT32_STACK_SLOT: { |
| 6206 int input_slot_index = iterator.Next(); |
| 6207 if (FLAG_print_code_verbose) { |
| 6208 PrintF("{input=%d}", input_slot_index); |
| 6209 } |
| 6210 break; |
| 6211 } |
| 6212 |
| 6213 case Translation::DOUBLE_STACK_SLOT: { |
| 6214 int input_slot_index = iterator.Next(); |
| 6215 if (FLAG_print_code_verbose) { |
| 6216 PrintF("{input=%d}", input_slot_index); |
| 6217 } |
| 6218 break; |
| 6219 } |
| 6220 |
| 6221 case Translation::LITERAL: { |
| 6222 unsigned literal_index = iterator.Next(); |
| 6223 if (FLAG_print_code_verbose) { |
| 6224 PrintF("{literal_id=%u}", literal_index); |
| 6225 } |
| 6226 break; |
| 6227 } |
| 6228 |
| 6229 case Translation::ARGUMENTS_OBJECT: |
| 6230 break; |
| 6231 } |
| 6232 if (FLAG_print_code_verbose) PrintF("\n"); |
| 6233 } |
| 6234 } |
| 6235 if (!FLAG_print_code_verbose) PrintF(" %12d\n", command_count); |
| 6236 } |
| 6237 } |
| 6238 |
| 6239 |
| 6240 void DeoptimizationOutputData::DeoptimizationOutputDataPrint() { |
| 6241 PrintF("Deoptimization Output Data (deopt points = %d)\n", |
| 6242 this->DeoptPoints()); |
| 6243 if (this->DeoptPoints() == 0) return; |
| 6244 |
| 6245 PrintF("%6s %8s %s\n", "ast id", "pc", "state"); |
| 6246 for (int i = 0; i < this->DeoptPoints(); i++) { |
| 6247 int pc_and_state = this->PcAndState(i)->value(); |
| 6248 PrintF("%6d %8d %s\n", |
| 6249 this->AstId(i)->value(), |
| 6250 FullCodeGenerator::PcField::decode(pc_and_state), |
| 6251 FullCodeGenerator::State2String( |
| 6252 FullCodeGenerator::StateField::decode(pc_and_state))); |
| 6253 } |
| 6254 } |
| 6255 |
| 6256 #endif |
| 6257 |
| 6258 |
| 5925 // Identify kind of code. | 6259 // Identify kind of code. |
| 5926 const char* Code::Kind2String(Kind kind) { | 6260 const char* Code::Kind2String(Kind kind) { |
| 5927 switch (kind) { | 6261 switch (kind) { |
| 5928 case FUNCTION: return "FUNCTION"; | 6262 case FUNCTION: return "FUNCTION"; |
| 6263 case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION"; |
| 5929 case STUB: return "STUB"; | 6264 case STUB: return "STUB"; |
| 5930 case BUILTIN: return "BUILTIN"; | 6265 case BUILTIN: return "BUILTIN"; |
| 5931 case LOAD_IC: return "LOAD_IC"; | 6266 case LOAD_IC: return "LOAD_IC"; |
| 5932 case KEYED_LOAD_IC: return "KEYED_LOAD_IC"; | 6267 case KEYED_LOAD_IC: return "KEYED_LOAD_IC"; |
| 5933 case STORE_IC: return "STORE_IC"; | 6268 case STORE_IC: return "STORE_IC"; |
| 5934 case KEYED_STORE_IC: return "KEYED_STORE_IC"; | 6269 case KEYED_STORE_IC: return "KEYED_STORE_IC"; |
| 5935 case CALL_IC: return "CALL_IC"; | 6270 case CALL_IC: return "CALL_IC"; |
| 5936 case KEYED_CALL_IC: return "KEYED_CALL_IC"; | 6271 case KEYED_CALL_IC: return "KEYED_CALL_IC"; |
| 5937 case BINARY_OP_IC: return "BINARY_OP_IC"; | 6272 case BINARY_OP_IC: return "BINARY_OP_IC"; |
| 6273 case TYPE_RECORDING_BINARY_OP_IC: return "TYPE_RECORDING_BINARY_OP_IC"; |
| 6274 case COMPARE_IC: return "COMPARE_IC"; |
| 5938 } | 6275 } |
| 5939 UNREACHABLE(); | 6276 UNREACHABLE(); |
| 5940 return NULL; | 6277 return NULL; |
| 5941 } | 6278 } |
| 5942 | 6279 |
| 5943 | 6280 |
| 5944 const char* Code::ICState2String(InlineCacheState state) { | 6281 const char* Code::ICState2String(InlineCacheState state) { |
| 5945 switch (state) { | 6282 switch (state) { |
| 5946 case UNINITIALIZED: return "UNINITIALIZED"; | 6283 case UNINITIALIZED: return "UNINITIALIZED"; |
| 5947 case PREMONOMORPHIC: return "PREMONOMORPHIC"; | 6284 case PREMONOMORPHIC: return "PREMONOMORPHIC"; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5964 case CALLBACKS: return "CALLBACKS"; | 6301 case CALLBACKS: return "CALLBACKS"; |
| 5965 case INTERCEPTOR: return "INTERCEPTOR"; | 6302 case INTERCEPTOR: return "INTERCEPTOR"; |
| 5966 case MAP_TRANSITION: return "MAP_TRANSITION"; | 6303 case MAP_TRANSITION: return "MAP_TRANSITION"; |
| 5967 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; | 6304 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; |
| 5968 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; | 6305 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; |
| 5969 } | 6306 } |
| 5970 UNREACHABLE(); | 6307 UNREACHABLE(); |
| 5971 return NULL; | 6308 return NULL; |
| 5972 } | 6309 } |
| 5973 | 6310 |
| 6311 |
| 5974 void Code::Disassemble(const char* name) { | 6312 void Code::Disassemble(const char* name) { |
| 5975 PrintF("kind = %s\n", Kind2String(kind())); | 6313 PrintF("kind = %s\n", Kind2String(kind())); |
| 5976 if (is_inline_cache_stub()) { | 6314 if (is_inline_cache_stub()) { |
| 5977 PrintF("ic_state = %s\n", ICState2String(ic_state())); | 6315 PrintF("ic_state = %s\n", ICState2String(ic_state())); |
| 5978 PrintF("ic_in_loop = %d\n", ic_in_loop() == IN_LOOP); | 6316 PrintF("ic_in_loop = %d\n", ic_in_loop() == IN_LOOP); |
| 5979 if (ic_state() == MONOMORPHIC) { | 6317 if (ic_state() == MONOMORPHIC) { |
| 5980 PrintF("type = %s\n", PropertyType2String(type())); | 6318 PrintF("type = %s\n", PropertyType2String(type())); |
| 5981 } | 6319 } |
| 5982 } | 6320 } |
| 5983 if ((name != NULL) && (name[0] != '\0')) { | 6321 if ((name != NULL) && (name[0] != '\0')) { |
| 5984 PrintF("name = %s\n", name); | 6322 PrintF("name = %s\n", name); |
| 5985 } | 6323 } |
| 6324 if (kind() == OPTIMIZED_FUNCTION) { |
| 6325 PrintF("stack_slots = %d\n", stack_slots()); |
| 6326 } |
| 5986 | 6327 |
| 5987 PrintF("Instructions (size = %d)\n", instruction_size()); | 6328 PrintF("Instructions (size = %d)\n", instruction_size()); |
| 5988 Disassembler::Decode(NULL, this); | 6329 Disassembler::Decode(NULL, this); |
| 5989 PrintF("\n"); | 6330 PrintF("\n"); |
| 5990 | 6331 |
| 6332 #ifdef DEBUG |
| 6333 if (kind() == FUNCTION) { |
| 6334 DeoptimizationOutputData* data = |
| 6335 DeoptimizationOutputData::cast(this->deoptimization_data()); |
| 6336 data->DeoptimizationOutputDataPrint(); |
| 6337 } else if (kind() == OPTIMIZED_FUNCTION) { |
| 6338 DeoptimizationInputData* data = |
| 6339 DeoptimizationInputData::cast(this->deoptimization_data()); |
| 6340 data->DeoptimizationInputDataPrint(); |
| 6341 } |
| 6342 PrintF("\n"); |
| 6343 #endif |
| 6344 |
| 6345 if (kind() == OPTIMIZED_FUNCTION) { |
| 6346 SafepointTable table(this); |
| 6347 PrintF("Safepoints (size = %u)\n", table.size()); |
| 6348 for (unsigned i = 0; i < table.length(); i++) { |
| 6349 unsigned pc_offset = table.GetPcOffset(i); |
| 6350 PrintF("%p %4d ", (instruction_start() + pc_offset), pc_offset); |
| 6351 table.PrintEntry(i); |
| 6352 PrintF(" (sp -> fp)"); |
| 6353 int deoptimization_index = table.GetDeoptimizationIndex(i); |
| 6354 if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) { |
| 6355 PrintF(" %6d", deoptimization_index); |
| 6356 } else { |
| 6357 PrintF(" <none>"); |
| 6358 } |
| 6359 PrintF("\n"); |
| 6360 } |
| 6361 PrintF("\n"); |
| 6362 } else if (kind() == FUNCTION) { |
| 6363 unsigned offset = stack_check_table_start(); |
| 6364 // If there is no stack check table, the "table start" will at or after |
| 6365 // (due to alignment) the end of the instruction stream. |
| 6366 if (static_cast<int>(offset) < instruction_size()) { |
| 6367 unsigned* address = |
| 6368 reinterpret_cast<unsigned*>(instruction_start() + offset); |
| 6369 unsigned length = address[0]; |
| 6370 PrintF("Stack checks (size = %u)\n", length); |
| 6371 PrintF("ast_id pc_offset\n"); |
| 6372 for (unsigned i = 0; i < length; ++i) { |
| 6373 unsigned index = (2 * i) + 1; |
| 6374 PrintF("%6u %9u\n", address[index], address[index + 1]); |
| 6375 } |
| 6376 PrintF("\n"); |
| 6377 } |
| 6378 } |
| 6379 |
| 5991 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 6380 PrintF("RelocInfo (size = %d)\n", relocation_size()); |
| 5992 for (RelocIterator it(this); !it.done(); it.next()) | 6381 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(); |
| 5993 it.rinfo()->Print(); | |
| 5994 PrintF("\n"); | 6382 PrintF("\n"); |
| 5995 } | 6383 } |
| 5996 #endif // ENABLE_DISASSEMBLER | 6384 #endif // ENABLE_DISASSEMBLER |
| 5997 | 6385 |
| 5998 | 6386 |
| 5999 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, | 6387 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, |
| 6000 int length) { | 6388 int length) { |
| 6001 Heap* heap = GetHeap(); | 6389 Heap* heap = GetHeap(); |
| 6002 // We should never end in here with a pixel or external array. | 6390 // We should never end in here with a pixel or external array. |
| 6003 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); | 6391 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); |
| (...skipping 2374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8378 // Clamp undefined to zero (default). All other types have been | 8766 // Clamp undefined to zero (default). All other types have been |
| 8379 // converted to a number type further up in the call chain. | 8767 // converted to a number type further up in the call chain. |
| 8380 ASSERT(value->IsUndefined()); | 8768 ASSERT(value->IsUndefined()); |
| 8381 } | 8769 } |
| 8382 set(index, cast_value); | 8770 set(index, cast_value); |
| 8383 } | 8771 } |
| 8384 return heap->AllocateHeapNumber(cast_value); | 8772 return heap->AllocateHeapNumber(cast_value); |
| 8385 } | 8773 } |
| 8386 | 8774 |
| 8387 | 8775 |
| 8388 Object* GlobalObject::GetPropertyCell(LookupResult* result) { | 8776 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
| 8389 ASSERT(!HasFastProperties()); | 8777 ASSERT(!HasFastProperties()); |
| 8390 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 8778 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 8391 ASSERT(value->IsJSGlobalPropertyCell()); | 8779 return JSGlobalPropertyCell::cast(value); |
| 8392 return value; | |
| 8393 } | 8780 } |
| 8394 | 8781 |
| 8395 | 8782 |
| 8396 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { | 8783 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { |
| 8397 ASSERT(!HasFastProperties()); | 8784 ASSERT(!HasFastProperties()); |
| 8398 Heap* heap = GetHeap(); | 8785 Heap* heap = GetHeap(); |
| 8399 int entry = property_dictionary()->FindEntry(name); | 8786 int entry = property_dictionary()->FindEntry(name); |
| 8400 if (entry == StringDictionary::kNotFound) { | 8787 if (entry == StringDictionary::kNotFound) { |
| 8401 Object* cell; | 8788 Object* cell; |
| 8402 { MaybeObject* maybe_cell = | 8789 { MaybeObject* maybe_cell = |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8641 int entry = cache->FindInsertionEntry(key.Hash()); | 9028 int entry = cache->FindInsertionEntry(key.Hash()); |
| 8642 // We store the value in the key slot, and compare the search key | 9029 // We store the value in the key slot, and compare the search key |
| 8643 // to the stored value with a custon IsMatch function during lookups. | 9030 // to the stored value with a custon IsMatch function during lookups. |
| 8644 cache->set(EntryToIndex(entry), value); | 9031 cache->set(EntryToIndex(entry), value); |
| 8645 cache->set(EntryToIndex(entry) + 1, value); | 9032 cache->set(EntryToIndex(entry) + 1, value); |
| 8646 cache->ElementAdded(); | 9033 cache->ElementAdded(); |
| 8647 return cache; | 9034 return cache; |
| 8648 } | 9035 } |
| 8649 | 9036 |
| 8650 | 9037 |
| 9038 void CompilationCacheTable::Remove(Object* value) { |
| 9039 Object* null_value = GetHeap()->null_value(); |
| 9040 for (int entry = 0, size = Capacity(); entry < size; entry++) { |
| 9041 int entry_index = EntryToIndex(entry); |
| 9042 int value_index = entry_index + 1; |
| 9043 if (get(value_index) == value) { |
| 9044 fast_set(this, entry_index, null_value); |
| 9045 fast_set(this, value_index, null_value); |
| 9046 ElementRemoved(); |
| 9047 } |
| 9048 } |
| 9049 return; |
| 9050 } |
| 9051 |
| 9052 |
| 8651 // SymbolsKey used for HashTable where key is array of symbols. | 9053 // SymbolsKey used for HashTable where key is array of symbols. |
| 8652 class SymbolsKey : public HashTableKey { | 9054 class SymbolsKey : public HashTableKey { |
| 8653 public: | 9055 public: |
| 8654 explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { } | 9056 explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { } |
| 8655 | 9057 |
| 8656 bool IsMatch(Object* symbols) { | 9058 bool IsMatch(Object* symbols) { |
| 8657 FixedArray* o = FixedArray::cast(symbols); | 9059 FixedArray* o = FixedArray::cast(symbols); |
| 8658 int len = symbols_->length(); | 9060 int len = symbols_->length(); |
| 8659 if (o->length() != len) return false; | 9061 if (o->length() != len) return false; |
| 8660 for (int i = 0; i < len; i++) { | 9062 for (int i = 0; i < len; i++) { |
| (...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9442 if (break_point_objects()->IsUndefined()) return 0; | 9844 if (break_point_objects()->IsUndefined()) return 0; |
| 9443 // Single beak point. | 9845 // Single beak point. |
| 9444 if (!break_point_objects()->IsFixedArray()) return 1; | 9846 if (!break_point_objects()->IsFixedArray()) return 1; |
| 9445 // Multiple break points. | 9847 // Multiple break points. |
| 9446 return FixedArray::cast(break_point_objects())->length(); | 9848 return FixedArray::cast(break_point_objects())->length(); |
| 9447 } | 9849 } |
| 9448 #endif | 9850 #endif |
| 9449 | 9851 |
| 9450 | 9852 |
| 9451 } } // namespace v8::internal | 9853 } } // namespace v8::internal |
| OLD | NEW |