| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 #include "scopeinfo.h" | 45 #include "scopeinfo.h" |
| 46 #include "string-stream.h" | 46 #include "string-stream.h" |
| 47 #include "utils.h" | 47 #include "utils.h" |
| 48 #include "vm-state-inl.h" | 48 #include "vm-state-inl.h" |
| 49 | 49 |
| 50 #ifdef ENABLE_DISASSEMBLER | 50 #ifdef ENABLE_DISASSEMBLER |
| 51 #include "disasm.h" | 51 #include "disasm.h" |
| 52 #include "disassembler.h" | 52 #include "disassembler.h" |
| 53 #endif | 53 #endif |
| 54 | 54 |
| 55 | |
| 56 namespace v8 { | 55 namespace v8 { |
| 57 namespace internal { | 56 namespace internal { |
| 58 | 57 |
| 59 // Getters and setters are stored in a fixed array property. These are | 58 // Getters and setters are stored in a fixed array property. These are |
| 60 // constants for their indices. | 59 // constants for their indices. |
| 61 const int kGetterIndex = 0; | 60 const int kGetterIndex = 0; |
| 62 const int kSetterIndex = 1; | 61 const int kSetterIndex = 1; |
| 63 | 62 |
| 64 | 63 |
| 65 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, | 64 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, |
| 66 Object* value) { | 65 Object* value) { |
| 67 Object* result; | 66 Object* result; |
| 68 { MaybeObject* maybe_result = Heap::AllocateJSObject(constructor); | 67 { MaybeObject* maybe_result = |
| 68 constructor->GetHeap()->AllocateJSObject(constructor); |
| 69 if (!maybe_result->ToObject(&result)) return maybe_result; | 69 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 70 } | 70 } |
| 71 JSValue::cast(result)->set_value(value); | 71 JSValue::cast(result)->set_value(value); |
| 72 return result; | 72 return result; |
| 73 } | 73 } |
| 74 | 74 |
| 75 | 75 |
| 76 MaybeObject* Object::ToObject(Context* global_context) { | 76 MaybeObject* Object::ToObject(Context* global_context) { |
| 77 if (IsNumber()) { | 77 if (IsNumber()) { |
| 78 return CreateJSValue(global_context->number_function(), this); | 78 return CreateJSValue(global_context->number_function(), this); |
| 79 } else if (IsBoolean()) { | 79 } else if (IsBoolean()) { |
| 80 return CreateJSValue(global_context->boolean_function(), this); | 80 return CreateJSValue(global_context->boolean_function(), this); |
| 81 } else if (IsString()) { | 81 } else if (IsString()) { |
| 82 return CreateJSValue(global_context->string_function(), this); | 82 return CreateJSValue(global_context->string_function(), this); |
| 83 } | 83 } |
| 84 ASSERT(IsJSObject()); | 84 ASSERT(IsJSObject()); |
| 85 return this; | 85 return this; |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 MaybeObject* Object::ToObject() { | 89 MaybeObject* Object::ToObject() { |
| 90 Context* global_context = Top::context()->global_context(); | |
| 91 if (IsJSObject()) { | 90 if (IsJSObject()) { |
| 92 return this; | 91 return this; |
| 93 } else if (IsNumber()) { | 92 } else if (IsNumber()) { |
| 93 Isolate* isolate = Isolate::Current(); |
| 94 Context* global_context = isolate->context()->global_context(); |
| 94 return CreateJSValue(global_context->number_function(), this); | 95 return CreateJSValue(global_context->number_function(), this); |
| 95 } else if (IsBoolean()) { | 96 } else if (IsBoolean()) { |
| 97 Isolate* isolate = HeapObject::cast(this)->GetIsolate(); |
| 98 Context* global_context = isolate->context()->global_context(); |
| 96 return CreateJSValue(global_context->boolean_function(), this); | 99 return CreateJSValue(global_context->boolean_function(), this); |
| 97 } else if (IsString()) { | 100 } else if (IsString()) { |
| 101 Isolate* isolate = HeapObject::cast(this)->GetIsolate(); |
| 102 Context* global_context = isolate->context()->global_context(); |
| 98 return CreateJSValue(global_context->string_function(), this); | 103 return CreateJSValue(global_context->string_function(), this); |
| 99 } | 104 } |
| 100 | 105 |
| 101 // Throw a type error. | 106 // Throw a type error. |
| 102 return Failure::InternalError(); | 107 return Failure::InternalError(); |
| 103 } | 108 } |
| 104 | 109 |
| 105 | 110 |
| 106 Object* Object::ToBoolean() { | 111 Object* Object::ToBoolean() { |
| 107 if (IsTrue()) return Heap::true_value(); | 112 if (IsTrue()) return this; |
| 108 if (IsFalse()) return Heap::false_value(); | 113 if (IsFalse()) return this; |
| 109 if (IsSmi()) { | 114 if (IsSmi()) { |
| 110 return Heap::ToBoolean(Smi::cast(this)->value() != 0); | 115 return Isolate::Current()->heap()->ToBoolean(Smi::cast(this)->value() != 0); |
| 111 } | 116 } |
| 112 if (IsUndefined() || IsNull()) return Heap::false_value(); | 117 if (IsUndefined() || IsNull()) { |
| 118 return HeapObject::cast(this)->GetHeap()->false_value(); |
| 119 } |
| 113 // Undetectable object is false | 120 // Undetectable object is false |
| 114 if (IsUndetectableObject()) { | 121 if (IsUndetectableObject()) { |
| 115 return Heap::false_value(); | 122 return HeapObject::cast(this)->GetHeap()->false_value(); |
| 116 } | 123 } |
| 117 if (IsString()) { | 124 if (IsString()) { |
| 118 return Heap::ToBoolean(String::cast(this)->length() != 0); | 125 return HeapObject::cast(this)->GetHeap()->ToBoolean( |
| 126 String::cast(this)->length() != 0); |
| 119 } | 127 } |
| 120 if (IsHeapNumber()) { | 128 if (IsHeapNumber()) { |
| 121 return HeapNumber::cast(this)->HeapNumberToBoolean(); | 129 return HeapNumber::cast(this)->HeapNumberToBoolean(); |
| 122 } | 130 } |
| 123 return Heap::true_value(); | 131 return Isolate::Current()->heap()->true_value(); |
| 124 } | 132 } |
| 125 | 133 |
| 126 | 134 |
| 127 void Object::Lookup(String* name, LookupResult* result) { | 135 void Object::Lookup(String* name, LookupResult* result) { |
| 128 if (IsJSObject()) return JSObject::cast(this)->Lookup(name, result); | 136 if (IsJSObject()) return JSObject::cast(this)->Lookup(name, result); |
| 129 Object* holder = NULL; | 137 Object* holder = NULL; |
| 130 Context* global_context = Top::context()->global_context(); | |
| 131 if (IsString()) { | 138 if (IsString()) { |
| 139 Heap* heap = HeapObject::cast(this)->GetHeap(); |
| 140 Context* global_context = heap->isolate()->context()->global_context(); |
| 132 holder = global_context->string_function()->instance_prototype(); | 141 holder = global_context->string_function()->instance_prototype(); |
| 133 } else if (IsNumber()) { | 142 } else if (IsNumber()) { |
| 143 Heap* heap = Isolate::Current()->heap(); |
| 144 Context* global_context = heap->isolate()->context()->global_context(); |
| 134 holder = global_context->number_function()->instance_prototype(); | 145 holder = global_context->number_function()->instance_prototype(); |
| 135 } else if (IsBoolean()) { | 146 } else if (IsBoolean()) { |
| 147 Heap* heap = HeapObject::cast(this)->GetHeap(); |
| 148 Context* global_context = heap->isolate()->context()->global_context(); |
| 136 holder = global_context->boolean_function()->instance_prototype(); | 149 holder = global_context->boolean_function()->instance_prototype(); |
| 137 } | 150 } |
| 138 ASSERT(holder != NULL); // Cannot handle null or undefined. | 151 ASSERT(holder != NULL); // Cannot handle null or undefined. |
| 139 JSObject::cast(holder)->Lookup(name, result); | 152 JSObject::cast(holder)->Lookup(name, result); |
| 140 } | 153 } |
| 141 | 154 |
| 142 | 155 |
| 143 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, | 156 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, |
| 144 String* name, | 157 String* name, |
| 145 PropertyAttributes* attributes) { | 158 PropertyAttributes* attributes) { |
| 146 LookupResult result; | 159 LookupResult result; |
| 147 Lookup(name, &result); | 160 Lookup(name, &result); |
| 148 MaybeObject* value = GetProperty(receiver, &result, name, attributes); | 161 MaybeObject* value = GetProperty(receiver, &result, name, attributes); |
| 149 ASSERT(*attributes <= ABSENT); | 162 ASSERT(*attributes <= ABSENT); |
| 150 return value; | 163 return value; |
| 151 } | 164 } |
| 152 | 165 |
| 153 | 166 |
| 154 MaybeObject* Object::GetPropertyWithCallback(Object* receiver, | 167 MaybeObject* Object::GetPropertyWithCallback(Object* receiver, |
| 155 Object* structure, | 168 Object* structure, |
| 156 String* name, | 169 String* name, |
| 157 Object* holder) { | 170 Object* holder) { |
| 171 Isolate* isolate = name->GetIsolate(); |
| 158 // To accommodate both the old and the new api we switch on the | 172 // To accommodate both the old and the new api we switch on the |
| 159 // data structure used to store the callbacks. Eventually proxy | 173 // data structure used to store the callbacks. Eventually proxy |
| 160 // callbacks should be phased out. | 174 // callbacks should be phased out. |
| 161 if (structure->IsProxy()) { | 175 if (structure->IsProxy()) { |
| 162 AccessorDescriptor* callback = | 176 AccessorDescriptor* callback = |
| 163 reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); | 177 reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); |
| 164 MaybeObject* value = (callback->getter)(receiver, callback->data); | 178 MaybeObject* value = (callback->getter)(receiver, callback->data); |
| 165 RETURN_IF_SCHEDULED_EXCEPTION(); | 179 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 166 return value; | 180 return value; |
| 167 } | 181 } |
| 168 | 182 |
| 169 // api style callbacks. | 183 // api style callbacks. |
| 170 if (structure->IsAccessorInfo()) { | 184 if (structure->IsAccessorInfo()) { |
| 171 AccessorInfo* data = AccessorInfo::cast(structure); | 185 AccessorInfo* data = AccessorInfo::cast(structure); |
| 172 Object* fun_obj = data->getter(); | 186 Object* fun_obj = data->getter(); |
| 173 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); | 187 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); |
| 174 HandleScope scope; | 188 HandleScope scope; |
| 175 JSObject* self = JSObject::cast(receiver); | 189 JSObject* self = JSObject::cast(receiver); |
| 176 JSObject* holder_handle = JSObject::cast(holder); | 190 JSObject* holder_handle = JSObject::cast(holder); |
| 177 Handle<String> key(name); | 191 Handle<String> key(name); |
| 178 LOG(ApiNamedPropertyAccess("load", self, name)); | 192 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); |
| 179 CustomArguments args(data->data(), self, holder_handle); | 193 CustomArguments args(isolate, data->data(), self, holder_handle); |
| 180 v8::AccessorInfo info(args.end()); | 194 v8::AccessorInfo info(args.end()); |
| 181 v8::Handle<v8::Value> result; | 195 v8::Handle<v8::Value> result; |
| 182 { | 196 { |
| 183 // Leaving JavaScript. | 197 // Leaving JavaScript. |
| 184 VMState state(EXTERNAL); | 198 VMState state(isolate, EXTERNAL); |
| 185 result = call_fun(v8::Utils::ToLocal(key), info); | 199 result = call_fun(v8::Utils::ToLocal(key), info); |
| 186 } | 200 } |
| 187 RETURN_IF_SCHEDULED_EXCEPTION(); | 201 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 188 if (result.IsEmpty()) return Heap::undefined_value(); | 202 if (result.IsEmpty()) { |
| 203 return isolate->heap()->undefined_value(); |
| 204 } |
| 189 return *v8::Utils::OpenHandle(*result); | 205 return *v8::Utils::OpenHandle(*result); |
| 190 } | 206 } |
| 191 | 207 |
| 192 // __defineGetter__ callback | 208 // __defineGetter__ callback |
| 193 if (structure->IsFixedArray()) { | 209 if (structure->IsFixedArray()) { |
| 194 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); | 210 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); |
| 195 if (getter->IsJSFunction()) { | 211 if (getter->IsJSFunction()) { |
| 196 return Object::GetPropertyWithDefinedGetter(receiver, | 212 return Object::GetPropertyWithDefinedGetter(receiver, |
| 197 JSFunction::cast(getter)); | 213 JSFunction::cast(getter)); |
| 198 } | 214 } |
| 199 // Getter is not a function. | 215 // Getter is not a function. |
| 200 return Heap::undefined_value(); | 216 return isolate->heap()->undefined_value(); |
| 201 } | 217 } |
| 202 | 218 |
| 203 UNREACHABLE(); | 219 UNREACHABLE(); |
| 204 return NULL; | 220 return NULL; |
| 205 } | 221 } |
| 206 | 222 |
| 207 | 223 |
| 208 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, | 224 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, |
| 209 JSFunction* getter) { | 225 JSFunction* getter) { |
| 210 HandleScope scope; | 226 HandleScope scope; |
| 211 Handle<JSFunction> fun(JSFunction::cast(getter)); | 227 Handle<JSFunction> fun(JSFunction::cast(getter)); |
| 212 Handle<Object> self(receiver); | 228 Handle<Object> self(receiver); |
| 213 #ifdef ENABLE_DEBUGGER_SUPPORT | 229 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 230 Debug* debug = fun->GetHeap()->isolate()->debug(); |
| 214 // Handle stepping into a getter if step into is active. | 231 // Handle stepping into a getter if step into is active. |
| 215 if (Debug::StepInActive()) { | 232 if (debug->StepInActive()) { |
| 216 Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false); | 233 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false); |
| 217 } | 234 } |
| 218 #endif | 235 #endif |
| 219 bool has_pending_exception; | 236 bool has_pending_exception; |
| 220 Handle<Object> result = | 237 Handle<Object> result = |
| 221 Execution::Call(fun, self, 0, NULL, &has_pending_exception); | 238 Execution::Call(fun, self, 0, NULL, &has_pending_exception); |
| 222 // Check for pending exception and return the result. | 239 // Check for pending exception and return the result. |
| 223 if (has_pending_exception) return Failure::Exception(); | 240 if (has_pending_exception) return Failure::Exception(); |
| 224 return *result; | 241 return *result; |
| 225 } | 242 } |
| 226 | 243 |
| 227 | 244 |
| 228 // Only deal with CALLBACKS and INTERCEPTOR | 245 // Only deal with CALLBACKS and INTERCEPTOR |
| 229 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( | 246 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( |
| 230 Object* receiver, | 247 Object* receiver, |
| 231 LookupResult* result, | 248 LookupResult* result, |
| 232 String* name, | 249 String* name, |
| 233 PropertyAttributes* attributes) { | 250 PropertyAttributes* attributes) { |
| 251 Heap* heap = name->GetHeap(); |
| 234 if (result->IsProperty()) { | 252 if (result->IsProperty()) { |
| 235 switch (result->type()) { | 253 switch (result->type()) { |
| 236 case CALLBACKS: { | 254 case CALLBACKS: { |
| 237 // Only allow API accessors. | 255 // Only allow API accessors. |
| 238 Object* obj = result->GetCallbackObject(); | 256 Object* obj = result->GetCallbackObject(); |
| 239 if (obj->IsAccessorInfo()) { | 257 if (obj->IsAccessorInfo()) { |
| 240 AccessorInfo* info = AccessorInfo::cast(obj); | 258 AccessorInfo* info = AccessorInfo::cast(obj); |
| 241 if (info->all_can_read()) { | 259 if (info->all_can_read()) { |
| 242 *attributes = result->GetAttributes(); | 260 *attributes = result->GetAttributes(); |
| 243 return GetPropertyWithCallback(receiver, | 261 return GetPropertyWithCallback(receiver, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 } | 293 } |
| 276 break; | 294 break; |
| 277 } | 295 } |
| 278 default: | 296 default: |
| 279 UNREACHABLE(); | 297 UNREACHABLE(); |
| 280 } | 298 } |
| 281 } | 299 } |
| 282 | 300 |
| 283 // No accessible property found. | 301 // No accessible property found. |
| 284 *attributes = ABSENT; | 302 *attributes = ABSENT; |
| 285 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET); | 303 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); |
| 286 return Heap::undefined_value(); | 304 return heap->undefined_value(); |
| 287 } | 305 } |
| 288 | 306 |
| 289 | 307 |
| 290 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( | 308 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( |
| 291 Object* receiver, | 309 Object* receiver, |
| 292 LookupResult* result, | 310 LookupResult* result, |
| 293 String* name, | 311 String* name, |
| 294 bool continue_search) { | 312 bool continue_search) { |
| 313 Heap* heap = name->GetHeap(); |
| 295 if (result->IsProperty()) { | 314 if (result->IsProperty()) { |
| 296 switch (result->type()) { | 315 switch (result->type()) { |
| 297 case CALLBACKS: { | 316 case CALLBACKS: { |
| 298 // Only allow API accessors. | 317 // Only allow API accessors. |
| 299 Object* obj = result->GetCallbackObject(); | 318 Object* obj = result->GetCallbackObject(); |
| 300 if (obj->IsAccessorInfo()) { | 319 if (obj->IsAccessorInfo()) { |
| 301 AccessorInfo* info = AccessorInfo::cast(obj); | 320 AccessorInfo* info = AccessorInfo::cast(obj); |
| 302 if (info->all_can_read()) { | 321 if (info->all_can_read()) { |
| 303 return result->GetAttributes(); | 322 return result->GetAttributes(); |
| 304 } | 323 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 continue_search); | 357 continue_search); |
| 339 } | 358 } |
| 340 break; | 359 break; |
| 341 } | 360 } |
| 342 | 361 |
| 343 default: | 362 default: |
| 344 UNREACHABLE(); | 363 UNREACHABLE(); |
| 345 } | 364 } |
| 346 } | 365 } |
| 347 | 366 |
| 348 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 367 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 349 return ABSENT; | 368 return ABSENT; |
| 350 } | 369 } |
| 351 | 370 |
| 352 | 371 |
| 353 Object* JSObject::GetNormalizedProperty(LookupResult* result) { | 372 Object* JSObject::GetNormalizedProperty(LookupResult* result) { |
| 354 ASSERT(!HasFastProperties()); | 373 ASSERT(!HasFastProperties()); |
| 355 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 374 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 356 if (IsGlobalObject()) { | 375 if (IsGlobalObject()) { |
| 357 value = JSGlobalPropertyCell::cast(value)->value(); | 376 value = JSGlobalPropertyCell::cast(value)->value(); |
| 358 } | 377 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 372 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); | 391 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); |
| 373 } | 392 } |
| 374 return value; | 393 return value; |
| 375 } | 394 } |
| 376 | 395 |
| 377 | 396 |
| 378 MaybeObject* JSObject::SetNormalizedProperty(String* name, | 397 MaybeObject* JSObject::SetNormalizedProperty(String* name, |
| 379 Object* value, | 398 Object* value, |
| 380 PropertyDetails details) { | 399 PropertyDetails details) { |
| 381 ASSERT(!HasFastProperties()); | 400 ASSERT(!HasFastProperties()); |
| 401 Heap* heap = name->GetHeap(); |
| 382 int entry = property_dictionary()->FindEntry(name); | 402 int entry = property_dictionary()->FindEntry(name); |
| 383 if (entry == StringDictionary::kNotFound) { | 403 if (entry == StringDictionary::kNotFound) { |
| 384 Object* store_value = value; | 404 Object* store_value = value; |
| 385 if (IsGlobalObject()) { | 405 if (IsGlobalObject()) { |
| 386 { MaybeObject* maybe_store_value = | 406 MaybeObject* maybe_store_value = |
| 387 Heap::AllocateJSGlobalPropertyCell(value); | 407 heap->AllocateJSGlobalPropertyCell(value); |
| 388 if (!maybe_store_value->ToObject(&store_value)) { | 408 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; |
| 389 return maybe_store_value; | |
| 390 } | |
| 391 } | |
| 392 } | 409 } |
| 393 Object* dict; | 410 Object* dict; |
| 394 { MaybeObject* maybe_dict = | 411 { MaybeObject* maybe_dict = |
| 395 property_dictionary()->Add(name, store_value, details); | 412 property_dictionary()->Add(name, store_value, details); |
| 396 if (!maybe_dict->ToObject(&dict)) return maybe_dict; | 413 if (!maybe_dict->ToObject(&dict)) return maybe_dict; |
| 397 } | 414 } |
| 398 set_properties(StringDictionary::cast(dict)); | 415 set_properties(StringDictionary::cast(dict)); |
| 399 return value; | 416 return value; |
| 400 } | 417 } |
| 401 // Preserve enumeration index. | 418 // Preserve enumeration index. |
| 402 details = PropertyDetails(details.attributes(), | 419 details = PropertyDetails(details.attributes(), |
| 403 details.type(), | 420 details.type(), |
| 404 property_dictionary()->DetailsAt(entry).index()); | 421 property_dictionary()->DetailsAt(entry).index()); |
| 405 if (IsGlobalObject()) { | 422 if (IsGlobalObject()) { |
| 406 JSGlobalPropertyCell* cell = | 423 JSGlobalPropertyCell* cell = |
| 407 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry)); | 424 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry)); |
| 408 cell->set_value(value); | 425 cell->set_value(value); |
| 409 // Please note we have to update the property details. | 426 // Please note we have to update the property details. |
| 410 property_dictionary()->DetailsAtPut(entry, details); | 427 property_dictionary()->DetailsAtPut(entry, details); |
| 411 } else { | 428 } else { |
| 412 property_dictionary()->SetEntry(entry, name, value, details); | 429 property_dictionary()->SetEntry(entry, name, value, details); |
| 413 } | 430 } |
| 414 return value; | 431 return value; |
| 415 } | 432 } |
| 416 | 433 |
| 417 | 434 |
| 418 MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { | 435 MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { |
| 419 ASSERT(!HasFastProperties()); | 436 ASSERT(!HasFastProperties()); |
| 437 Heap* heap = GetHeap(); |
| 420 StringDictionary* dictionary = property_dictionary(); | 438 StringDictionary* dictionary = property_dictionary(); |
| 421 int entry = dictionary->FindEntry(name); | 439 int entry = dictionary->FindEntry(name); |
| 422 if (entry != StringDictionary::kNotFound) { | 440 if (entry != StringDictionary::kNotFound) { |
| 423 // If we have a global object set the cell to the hole. | 441 // If we have a global object set the cell to the hole. |
| 424 if (IsGlobalObject()) { | 442 if (IsGlobalObject()) { |
| 425 PropertyDetails details = dictionary->DetailsAt(entry); | 443 PropertyDetails details = dictionary->DetailsAt(entry); |
| 426 if (details.IsDontDelete()) { | 444 if (details.IsDontDelete()) { |
| 427 if (mode != FORCE_DELETION) return Heap::false_value(); | 445 if (mode != FORCE_DELETION) return heap->false_value(); |
| 428 // When forced to delete global properties, we have to make a | 446 // When forced to delete global properties, we have to make a |
| 429 // map change to invalidate any ICs that think they can load | 447 // map change to invalidate any ICs that think they can load |
| 430 // from the DontDelete cell without checking if it contains | 448 // from the DontDelete cell without checking if it contains |
| 431 // the hole value. | 449 // the hole value. |
| 432 Object* new_map; | 450 Object* new_map; |
| 433 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | 451 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
| 434 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 452 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 435 } | 453 } |
| 436 set_map(Map::cast(new_map)); | 454 set_map(Map::cast(new_map)); |
| 437 } | 455 } |
| 438 JSGlobalPropertyCell* cell = | 456 JSGlobalPropertyCell* cell = |
| 439 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); | 457 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); |
| 440 cell->set_value(Heap::the_hole_value()); | 458 cell->set_value(heap->the_hole_value()); |
| 441 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 459 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| 442 } else { | 460 } else { |
| 443 return dictionary->DeleteProperty(entry, mode); | 461 return dictionary->DeleteProperty(entry, mode); |
| 444 } | 462 } |
| 445 } | 463 } |
| 446 return Heap::true_value(); | 464 return heap->true_value(); |
| 447 } | 465 } |
| 448 | 466 |
| 449 | 467 |
| 450 bool JSObject::IsDirty() { | 468 bool JSObject::IsDirty() { |
| 451 Object* cons_obj = map()->constructor(); | 469 Object* cons_obj = map()->constructor(); |
| 452 if (!cons_obj->IsJSFunction()) | 470 if (!cons_obj->IsJSFunction()) |
| 453 return true; | 471 return true; |
| 454 JSFunction* fun = JSFunction::cast(cons_obj); | 472 JSFunction* fun = JSFunction::cast(cons_obj); |
| 455 if (!fun->shared()->IsApiFunction()) | 473 if (!fun->shared()->IsApiFunction()) |
| 456 return true; | 474 return true; |
| 457 // If the object is fully fast case and has the same map it was | 475 // If the object is fully fast case and has the same map it was |
| 458 // created with then no changes can have been made to it. | 476 // created with then no changes can have been made to it. |
| 459 return map() != fun->initial_map() | 477 return map() != fun->initial_map() |
| 460 || !HasFastElements() | 478 || !HasFastElements() |
| 461 || !HasFastProperties(); | 479 || !HasFastProperties(); |
| 462 } | 480 } |
| 463 | 481 |
| 464 | 482 |
| 465 MaybeObject* Object::GetProperty(Object* receiver, | 483 MaybeObject* Object::GetProperty(Object* receiver, |
| 466 LookupResult* result, | 484 LookupResult* result, |
| 467 String* name, | 485 String* name, |
| 468 PropertyAttributes* attributes) { | 486 PropertyAttributes* attributes) { |
| 469 // Make sure that the top context does not change when doing | 487 // Make sure that the top context does not change when doing |
| 470 // callbacks or interceptor calls. | 488 // callbacks or interceptor calls. |
| 471 AssertNoContextChange ncc; | 489 AssertNoContextChange ncc; |
| 490 Heap* heap = name->GetHeap(); |
| 472 | 491 |
| 473 // Traverse the prototype chain from the current object (this) to | 492 // Traverse the prototype chain from the current object (this) to |
| 474 // the holder and check for access rights. This avoid traversing the | 493 // the holder and check for access rights. This avoid traversing the |
| 475 // objects more than once in case of interceptors, because the | 494 // objects more than once in case of interceptors, because the |
| 476 // holder will always be the interceptor holder and the search may | 495 // holder will always be the interceptor holder and the search may |
| 477 // only continue with a current object just after the interceptor | 496 // only continue with a current object just after the interceptor |
| 478 // holder in the prototype chain. | 497 // holder in the prototype chain. |
| 479 Object* last = result->IsProperty() ? result->holder() : Heap::null_value(); | 498 Object* last = result->IsProperty() ? result->holder() : heap->null_value(); |
| 480 for (Object* current = this; true; current = current->GetPrototype()) { | 499 for (Object* current = this; true; current = current->GetPrototype()) { |
| 481 if (current->IsAccessCheckNeeded()) { | 500 if (current->IsAccessCheckNeeded()) { |
| 482 // Check if we're allowed to read from the current object. Note | 501 // Check if we're allowed to read from the current object. Note |
| 483 // that even though we may not actually end up loading the named | 502 // that even though we may not actually end up loading the named |
| 484 // property from the current object, we still check that we have | 503 // property from the current object, we still check that we have |
| 485 // access to it. | 504 // access to it. |
| 486 JSObject* checked = JSObject::cast(current); | 505 JSObject* checked = JSObject::cast(current); |
| 487 if (!Top::MayNamedAccess(checked, name, v8::ACCESS_GET)) { | 506 if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) { |
| 488 return checked->GetPropertyWithFailedAccessCheck(receiver, | 507 return checked->GetPropertyWithFailedAccessCheck(receiver, |
| 489 result, | 508 result, |
| 490 name, | 509 name, |
| 491 attributes); | 510 attributes); |
| 492 } | 511 } |
| 493 } | 512 } |
| 494 // Stop traversing the chain once we reach the last object in the | 513 // Stop traversing the chain once we reach the last object in the |
| 495 // chain; either the holder of the result or null in case of an | 514 // chain; either the holder of the result or null in case of an |
| 496 // absent property. | 515 // absent property. |
| 497 if (current == last) break; | 516 if (current == last) break; |
| 498 } | 517 } |
| 499 | 518 |
| 500 if (!result->IsProperty()) { | 519 if (!result->IsProperty()) { |
| 501 *attributes = ABSENT; | 520 *attributes = ABSENT; |
| 502 return Heap::undefined_value(); | 521 return heap->undefined_value(); |
| 503 } | 522 } |
| 504 *attributes = result->GetAttributes(); | 523 *attributes = result->GetAttributes(); |
| 505 Object* value; | 524 Object* value; |
| 506 JSObject* holder = result->holder(); | 525 JSObject* holder = result->holder(); |
| 507 switch (result->type()) { | 526 switch (result->type()) { |
| 508 case NORMAL: | 527 case NORMAL: |
| 509 value = holder->GetNormalizedProperty(result); | 528 value = holder->GetNormalizedProperty(result); |
| 510 ASSERT(!value->IsTheHole() || result->IsReadOnly()); | 529 ASSERT(!value->IsTheHole() || result->IsReadOnly()); |
| 511 return value->IsTheHole() ? Heap::undefined_value() : value; | 530 return value->IsTheHole() ? heap->undefined_value() : value; |
| 512 case FIELD: | 531 case FIELD: |
| 513 value = holder->FastPropertyAt(result->GetFieldIndex()); | 532 value = holder->FastPropertyAt(result->GetFieldIndex()); |
| 514 ASSERT(!value->IsTheHole() || result->IsReadOnly()); | 533 ASSERT(!value->IsTheHole() || result->IsReadOnly()); |
| 515 return value->IsTheHole() ? Heap::undefined_value() : value; | 534 return value->IsTheHole() ? heap->undefined_value() : value; |
| 516 case CONSTANT_FUNCTION: | 535 case CONSTANT_FUNCTION: |
| 517 return result->GetConstantFunction(); | 536 return result->GetConstantFunction(); |
| 518 case CALLBACKS: | 537 case CALLBACKS: |
| 519 return GetPropertyWithCallback(receiver, | 538 return GetPropertyWithCallback(receiver, |
| 520 result->GetCallbackObject(), | 539 result->GetCallbackObject(), |
| 521 name, | 540 name, |
| 522 holder); | 541 holder); |
| 523 case INTERCEPTOR: { | 542 case INTERCEPTOR: { |
| 524 JSObject* recvr = JSObject::cast(receiver); | 543 JSObject* recvr = JSObject::cast(receiver); |
| 525 return holder->GetPropertyWithInterceptor(recvr, name, attributes); | 544 return holder->GetPropertyWithInterceptor(recvr, name, attributes); |
| 526 } | 545 } |
| 527 default: | 546 default: |
| 528 UNREACHABLE(); | 547 UNREACHABLE(); |
| 529 return NULL; | 548 return NULL; |
| 530 } | 549 } |
| 531 } | 550 } |
| 532 | 551 |
| 533 | 552 |
| 534 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { | 553 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { |
| 535 if (IsJSObject()) { | 554 if (IsJSObject()) { |
| 536 return JSObject::cast(this)->GetElementWithReceiver(receiver, index); | 555 return JSObject::cast(this)->GetElementWithReceiver(receiver, index); |
| 537 } | 556 } |
| 538 | 557 |
| 539 Object* holder = NULL; | 558 Object* holder = NULL; |
| 540 Context* global_context = Top::context()->global_context(); | 559 Context* global_context = Isolate::Current()->context()->global_context(); |
| 541 if (IsString()) { | 560 if (IsString()) { |
| 542 holder = global_context->string_function()->instance_prototype(); | 561 holder = global_context->string_function()->instance_prototype(); |
| 543 } else if (IsNumber()) { | 562 } else if (IsNumber()) { |
| 544 holder = global_context->number_function()->instance_prototype(); | 563 holder = global_context->number_function()->instance_prototype(); |
| 545 } else if (IsBoolean()) { | 564 } else if (IsBoolean()) { |
| 546 holder = global_context->boolean_function()->instance_prototype(); | 565 holder = global_context->boolean_function()->instance_prototype(); |
| 547 } else { | 566 } else { |
| 548 // Undefined and null have no indexed properties. | 567 // Undefined and null have no indexed properties. |
| 549 ASSERT(IsUndefined() || IsNull()); | 568 ASSERT(IsUndefined() || IsNull()); |
| 550 return Heap::undefined_value(); | 569 return HEAP->undefined_value(); |
| 551 } | 570 } |
| 552 | 571 |
| 553 return JSObject::cast(holder)->GetElementWithReceiver(receiver, index); | 572 return JSObject::cast(holder)->GetElementWithReceiver(receiver, index); |
| 554 } | 573 } |
| 555 | 574 |
| 556 | 575 |
| 557 Object* Object::GetPrototype() { | 576 Object* Object::GetPrototype() { |
| 558 // The object is either a number, a string, a boolean, or a real JS object. | 577 // The object is either a number, a string, a boolean, or a real JS object. |
| 559 if (IsJSObject()) return JSObject::cast(this)->map()->prototype(); | 578 if (IsJSObject()) return JSObject::cast(this)->map()->prototype(); |
| 560 Context* context = Top::context()->global_context(); | 579 Heap* heap = Isolate::Current()->heap(); |
| 580 Context* context = heap->isolate()->context()->global_context(); |
| 561 | 581 |
| 562 if (IsNumber()) return context->number_function()->instance_prototype(); | 582 if (IsNumber()) return context->number_function()->instance_prototype(); |
| 563 if (IsString()) return context->string_function()->instance_prototype(); | 583 if (IsString()) return context->string_function()->instance_prototype(); |
| 564 if (IsBoolean()) { | 584 if (IsBoolean()) { |
| 565 return context->boolean_function()->instance_prototype(); | 585 return context->boolean_function()->instance_prototype(); |
| 566 } else { | 586 } else { |
| 567 return Heap::null_value(); | 587 return heap->null_value(); |
| 568 } | 588 } |
| 569 } | 589 } |
| 570 | 590 |
| 571 | 591 |
| 572 void Object::ShortPrint(FILE* out) { | 592 void Object::ShortPrint(FILE* out) { |
| 573 HeapStringAllocator allocator; | 593 HeapStringAllocator allocator; |
| 574 StringStream accumulator(&allocator); | 594 StringStream accumulator(&allocator); |
| 575 ShortPrint(&accumulator); | 595 ShortPrint(&accumulator); |
| 576 accumulator.OutputToFile(out); | 596 accumulator.OutputToFile(out); |
| 577 } | 597 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 return false; | 651 return false; |
| 632 } | 652 } |
| 633 | 653 |
| 634 | 654 |
| 635 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) { | 655 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) { |
| 636 #ifdef DEBUG | 656 #ifdef DEBUG |
| 637 // Do not attempt to flatten in debug mode when allocation is not | 657 // Do not attempt to flatten in debug mode when allocation is not |
| 638 // allowed. This is to avoid an assertion failure when allocating. | 658 // allowed. This is to avoid an assertion failure when allocating. |
| 639 // Flattening strings is the only case where we always allow | 659 // Flattening strings is the only case where we always allow |
| 640 // allocation because no GC is performed if the allocation fails. | 660 // allocation because no GC is performed if the allocation fails. |
| 641 if (!Heap::IsAllocationAllowed()) return this; | 661 if (!HEAP->IsAllocationAllowed()) return this; |
| 642 #endif | 662 #endif |
| 643 | 663 |
| 664 Heap* heap = GetHeap(); |
| 644 switch (StringShape(this).representation_tag()) { | 665 switch (StringShape(this).representation_tag()) { |
| 645 case kConsStringTag: { | 666 case kConsStringTag: { |
| 646 ConsString* cs = ConsString::cast(this); | 667 ConsString* cs = ConsString::cast(this); |
| 647 if (cs->second()->length() == 0) { | 668 if (cs->second()->length() == 0) { |
| 648 return cs->first(); | 669 return cs->first(); |
| 649 } | 670 } |
| 650 // There's little point in putting the flat string in new space if the | 671 // There's little point in putting the flat string in new space if the |
| 651 // cons string is in old space. It can never get GCed until there is | 672 // cons string is in old space. It can never get GCed until there is |
| 652 // an old space GC. | 673 // an old space GC. |
| 653 PretenureFlag tenure = Heap::InNewSpace(this) ? pretenure : TENURED; | 674 PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED; |
| 654 int len = length(); | 675 int len = length(); |
| 655 Object* object; | 676 Object* object; |
| 656 String* result; | 677 String* result; |
| 657 if (IsAsciiRepresentation()) { | 678 if (IsAsciiRepresentation()) { |
| 658 { MaybeObject* maybe_object = Heap::AllocateRawAsciiString(len, tenure); | 679 { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure); |
| 659 if (!maybe_object->ToObject(&object)) return maybe_object; | 680 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 660 } | 681 } |
| 661 result = String::cast(object); | 682 result = String::cast(object); |
| 662 String* first = cs->first(); | 683 String* first = cs->first(); |
| 663 int first_length = first->length(); | 684 int first_length = first->length(); |
| 664 char* dest = SeqAsciiString::cast(result)->GetChars(); | 685 char* dest = SeqAsciiString::cast(result)->GetChars(); |
| 665 WriteToFlat(first, dest, 0, first_length); | 686 WriteToFlat(first, dest, 0, first_length); |
| 666 String* second = cs->second(); | 687 String* second = cs->second(); |
| 667 WriteToFlat(second, | 688 WriteToFlat(second, |
| 668 dest + first_length, | 689 dest + first_length, |
| 669 0, | 690 0, |
| 670 len - first_length); | 691 len - first_length); |
| 671 } else { | 692 } else { |
| 672 { MaybeObject* maybe_object = | 693 { MaybeObject* maybe_object = |
| 673 Heap::AllocateRawTwoByteString(len, tenure); | 694 heap->AllocateRawTwoByteString(len, tenure); |
| 674 if (!maybe_object->ToObject(&object)) return maybe_object; | 695 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 675 } | 696 } |
| 676 result = String::cast(object); | 697 result = String::cast(object); |
| 677 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); | 698 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); |
| 678 String* first = cs->first(); | 699 String* first = cs->first(); |
| 679 int first_length = first->length(); | 700 int first_length = first->length(); |
| 680 WriteToFlat(first, dest, 0, first_length); | 701 WriteToFlat(first, dest, 0, first_length); |
| 681 String* second = cs->second(); | 702 String* second = cs->second(); |
| 682 WriteToFlat(second, | 703 WriteToFlat(second, |
| 683 dest + first_length, | 704 dest + first_length, |
| 684 0, | 705 0, |
| 685 len - first_length); | 706 len - first_length); |
| 686 } | 707 } |
| 687 cs->set_first(result); | 708 cs->set_first(result); |
| 688 cs->set_second(Heap::empty_string()); | 709 cs->set_second(heap->empty_string()); |
| 689 return result; | 710 return result; |
| 690 } | 711 } |
| 691 default: | 712 default: |
| 692 return this; | 713 return this; |
| 693 } | 714 } |
| 694 } | 715 } |
| 695 | 716 |
| 696 | 717 |
| 697 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { | 718 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { |
| 698 // Externalizing twice leaks the external resource, so it's | 719 // Externalizing twice leaks the external resource, so it's |
| 699 // prohibited by the API. | 720 // prohibited by the API. |
| 700 ASSERT(!this->IsExternalString()); | 721 ASSERT(!this->IsExternalString()); |
| 701 #ifdef DEBUG | 722 #ifdef DEBUG |
| 702 if (FLAG_enable_slow_asserts) { | 723 if (FLAG_enable_slow_asserts) { |
| 703 // Assert that the resource and the string are equivalent. | 724 // Assert that the resource and the string are equivalent. |
| 704 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 725 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
| 705 ScopedVector<uc16> smart_chars(this->length()); | 726 ScopedVector<uc16> smart_chars(this->length()); |
| 706 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 727 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 707 ASSERT(memcmp(smart_chars.start(), | 728 ASSERT(memcmp(smart_chars.start(), |
| 708 resource->data(), | 729 resource->data(), |
| 709 resource->length() * sizeof(smart_chars[0])) == 0); | 730 resource->length() * sizeof(smart_chars[0])) == 0); |
| 710 } | 731 } |
| 711 #endif // DEBUG | 732 #endif // DEBUG |
| 712 | 733 Heap* heap = GetHeap(); |
| 713 int size = this->Size(); // Byte size of the original string. | 734 int size = this->Size(); // Byte size of the original string. |
| 714 if (size < ExternalString::kSize) { | 735 if (size < ExternalString::kSize) { |
| 715 // The string is too small to fit an external String in its place. This can | 736 // The string is too small to fit an external String in its place. This can |
| 716 // only happen for zero length strings. | 737 // only happen for zero length strings. |
| 717 return false; | 738 return false; |
| 718 } | 739 } |
| 719 ASSERT(size >= ExternalString::kSize); | 740 ASSERT(size >= ExternalString::kSize); |
| 720 bool is_ascii = this->IsAsciiRepresentation(); | 741 bool is_ascii = this->IsAsciiRepresentation(); |
| 721 bool is_symbol = this->IsSymbol(); | 742 bool is_symbol = this->IsSymbol(); |
| 722 int length = this->length(); | 743 int length = this->length(); |
| 723 int hash_field = this->hash_field(); | 744 int hash_field = this->hash_field(); |
| 724 | 745 |
| 725 // Morph the object to an external string by adjusting the map and | 746 // Morph the object to an external string by adjusting the map and |
| 726 // reinitializing the fields. | 747 // reinitializing the fields. |
| 727 this->set_map(is_ascii ? | 748 this->set_map(is_ascii ? |
| 728 Heap::external_string_with_ascii_data_map() : | 749 heap->external_string_with_ascii_data_map() : |
| 729 Heap::external_string_map()); | 750 heap->external_string_map()); |
| 730 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); | 751 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); |
| 731 self->set_length(length); | 752 self->set_length(length); |
| 732 self->set_hash_field(hash_field); | 753 self->set_hash_field(hash_field); |
| 733 self->set_resource(resource); | 754 self->set_resource(resource); |
| 734 // Additionally make the object into an external symbol if the original string | 755 // Additionally make the object into an external symbol if the original string |
| 735 // was a symbol to start with. | 756 // was a symbol to start with. |
| 736 if (is_symbol) { | 757 if (is_symbol) { |
| 737 self->Hash(); // Force regeneration of the hash value. | 758 self->Hash(); // Force regeneration of the hash value. |
| 738 // Now morph this external string into a external symbol. | 759 // Now morph this external string into a external symbol. |
| 739 this->set_map(is_ascii ? | 760 this->set_map(is_ascii ? |
| 740 Heap::external_symbol_with_ascii_data_map() : | 761 heap->external_symbol_with_ascii_data_map() : |
| 741 Heap::external_symbol_map()); | 762 heap->external_symbol_map()); |
| 742 } | 763 } |
| 743 | 764 |
| 744 // Fill the remainder of the string with dead wood. | 765 // Fill the remainder of the string with dead wood. |
| 745 int new_size = this->Size(); // Byte size of the external String object. | 766 int new_size = this->Size(); // Byte size of the external String object. |
| 746 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size); | 767 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); |
| 747 return true; | 768 return true; |
| 748 } | 769 } |
| 749 | 770 |
| 750 | 771 |
| 751 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { | 772 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { |
| 752 #ifdef DEBUG | 773 #ifdef DEBUG |
| 753 if (FLAG_enable_slow_asserts) { | 774 if (FLAG_enable_slow_asserts) { |
| 754 // Assert that the resource and the string are equivalent. | 775 // Assert that the resource and the string are equivalent. |
| 755 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 776 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
| 756 ScopedVector<char> smart_chars(this->length()); | 777 ScopedVector<char> smart_chars(this->length()); |
| 757 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 778 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 758 ASSERT(memcmp(smart_chars.start(), | 779 ASSERT(memcmp(smart_chars.start(), |
| 759 resource->data(), | 780 resource->data(), |
| 760 resource->length() * sizeof(smart_chars[0])) == 0); | 781 resource->length() * sizeof(smart_chars[0])) == 0); |
| 761 } | 782 } |
| 762 #endif // DEBUG | 783 #endif // DEBUG |
| 763 | 784 Heap* heap = GetHeap(); |
| 764 int size = this->Size(); // Byte size of the original string. | 785 int size = this->Size(); // Byte size of the original string. |
| 765 if (size < ExternalString::kSize) { | 786 if (size < ExternalString::kSize) { |
| 766 // The string is too small to fit an external String in its place. This can | 787 // The string is too small to fit an external String in its place. This can |
| 767 // only happen for zero length strings. | 788 // only happen for zero length strings. |
| 768 return false; | 789 return false; |
| 769 } | 790 } |
| 770 ASSERT(size >= ExternalString::kSize); | 791 ASSERT(size >= ExternalString::kSize); |
| 771 bool is_symbol = this->IsSymbol(); | 792 bool is_symbol = this->IsSymbol(); |
| 772 int length = this->length(); | 793 int length = this->length(); |
| 773 int hash_field = this->hash_field(); | 794 int hash_field = this->hash_field(); |
| 774 | 795 |
| 775 // Morph the object to an external string by adjusting the map and | 796 // Morph the object to an external string by adjusting the map and |
| 776 // reinitializing the fields. | 797 // reinitializing the fields. |
| 777 this->set_map(Heap::external_ascii_string_map()); | 798 this->set_map(heap->external_ascii_string_map()); |
| 778 ExternalAsciiString* self = ExternalAsciiString::cast(this); | 799 ExternalAsciiString* self = ExternalAsciiString::cast(this); |
| 779 self->set_length(length); | 800 self->set_length(length); |
| 780 self->set_hash_field(hash_field); | 801 self->set_hash_field(hash_field); |
| 781 self->set_resource(resource); | 802 self->set_resource(resource); |
| 782 // Additionally make the object into an external symbol if the original string | 803 // Additionally make the object into an external symbol if the original string |
| 783 // was a symbol to start with. | 804 // was a symbol to start with. |
| 784 if (is_symbol) { | 805 if (is_symbol) { |
| 785 self->Hash(); // Force regeneration of the hash value. | 806 self->Hash(); // Force regeneration of the hash value. |
| 786 // Now morph this external string into a external symbol. | 807 // Now morph this external string into a external symbol. |
| 787 this->set_map(Heap::external_ascii_symbol_map()); | 808 this->set_map(heap->external_ascii_symbol_map()); |
| 788 } | 809 } |
| 789 | 810 |
| 790 // Fill the remainder of the string with dead wood. | 811 // Fill the remainder of the string with dead wood. |
| 791 int new_size = this->Size(); // Byte size of the external String object. | 812 int new_size = this->Size(); // Byte size of the external String object. |
| 792 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size); | 813 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); |
| 793 return true; | 814 return true; |
| 794 } | 815 } |
| 795 | 816 |
| 796 | 817 |
| 797 void String::StringShortPrint(StringStream* accumulator) { | 818 void String::StringShortPrint(StringStream* accumulator) { |
| 798 int len = length(); | 819 int len = length(); |
| 799 if (len > kMaxShortPrintLength) { | 820 if (len > kMaxShortPrintLength) { |
| 800 accumulator->Add("<Very long string[%u]>", len); | 821 accumulator->Add("<Very long string[%u]>", len); |
| 801 return; | 822 return; |
| 802 } | 823 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 } | 902 } |
| 882 } | 903 } |
| 883 if (!printed) { | 904 if (!printed) { |
| 884 accumulator->Add("<JS Function>"); | 905 accumulator->Add("<JS Function>"); |
| 885 } | 906 } |
| 886 break; | 907 break; |
| 887 } | 908 } |
| 888 // All other JSObjects are rather similar to each other (JSObject, | 909 // All other JSObjects are rather similar to each other (JSObject, |
| 889 // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue). | 910 // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue). |
| 890 default: { | 911 default: { |
| 912 Heap* heap = GetHeap(); |
| 891 Object* constructor = map()->constructor(); | 913 Object* constructor = map()->constructor(); |
| 892 bool printed = false; | 914 bool printed = false; |
| 893 if (constructor->IsHeapObject() && | 915 if (constructor->IsHeapObject() && |
| 894 !Heap::Contains(HeapObject::cast(constructor))) { | 916 !heap->Contains(HeapObject::cast(constructor))) { |
| 895 accumulator->Add("!!!INVALID CONSTRUCTOR!!!"); | 917 accumulator->Add("!!!INVALID CONSTRUCTOR!!!"); |
| 896 } else { | 918 } else { |
| 897 bool global_object = IsJSGlobalProxy(); | 919 bool global_object = IsJSGlobalProxy(); |
| 898 if (constructor->IsJSFunction()) { | 920 if (constructor->IsJSFunction()) { |
| 899 if (!Heap::Contains(JSFunction::cast(constructor)->shared())) { | 921 if (!heap->Contains(JSFunction::cast(constructor)->shared())) { |
| 900 accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!"); | 922 accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!"); |
| 901 } else { | 923 } else { |
| 902 Object* constructor_name = | 924 Object* constructor_name = |
| 903 JSFunction::cast(constructor)->shared()->name(); | 925 JSFunction::cast(constructor)->shared()->name(); |
| 904 if (constructor_name->IsString()) { | 926 if (constructor_name->IsString()) { |
| 905 String* str = String::cast(constructor_name); | 927 String* str = String::cast(constructor_name); |
| 906 if (str->length() > 0) { | 928 if (str->length() > 0) { |
| 907 bool vowel = AnWord(str); | 929 bool vowel = AnWord(str); |
| 908 accumulator->Add("<%sa%s ", | 930 accumulator->Add("<%sa%s ", |
| 909 global_object ? "Global Object: " : "", | 931 global_object ? "Global Object: " : "", |
| (...skipping 14 matching lines...) Expand all Loading... |
| 924 JSValue::cast(this)->value()->ShortPrint(accumulator); | 946 JSValue::cast(this)->value()->ShortPrint(accumulator); |
| 925 } | 947 } |
| 926 accumulator->Put('>'); | 948 accumulator->Put('>'); |
| 927 break; | 949 break; |
| 928 } | 950 } |
| 929 } | 951 } |
| 930 } | 952 } |
| 931 | 953 |
| 932 | 954 |
| 933 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { | 955 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { |
| 934 // if (!Heap::InNewSpace(this)) PrintF("*", this); | 956 // if (!HEAP->InNewSpace(this)) PrintF("*", this); |
| 935 if (!Heap::Contains(this)) { | 957 Heap* heap = GetHeap(); |
| 958 if (!heap->Contains(this)) { |
| 936 accumulator->Add("!!!INVALID POINTER!!!"); | 959 accumulator->Add("!!!INVALID POINTER!!!"); |
| 937 return; | 960 return; |
| 938 } | 961 } |
| 939 if (!Heap::Contains(map())) { | 962 if (!heap->Contains(map())) { |
| 940 accumulator->Add("!!!INVALID MAP!!!"); | 963 accumulator->Add("!!!INVALID MAP!!!"); |
| 941 return; | 964 return; |
| 942 } | 965 } |
| 943 | 966 |
| 944 accumulator->Add("%p ", this); | 967 accumulator->Add("%p ", this); |
| 945 | 968 |
| 946 if (IsString()) { | 969 if (IsString()) { |
| 947 String::cast(this)->StringShortPrint(accumulator); | 970 String::cast(this)->StringShortPrint(accumulator); |
| 948 return; | 971 return; |
| 949 } | 972 } |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 // NaN, +0, and -0 should return the false object | 1171 // NaN, +0, and -0 should return the false object |
| 1149 #if __BYTE_ORDER == __LITTLE_ENDIAN | 1172 #if __BYTE_ORDER == __LITTLE_ENDIAN |
| 1150 union IeeeDoubleLittleEndianArchType u; | 1173 union IeeeDoubleLittleEndianArchType u; |
| 1151 #elif __BYTE_ORDER == __BIG_ENDIAN | 1174 #elif __BYTE_ORDER == __BIG_ENDIAN |
| 1152 union IeeeDoubleBigEndianArchType u; | 1175 union IeeeDoubleBigEndianArchType u; |
| 1153 #endif | 1176 #endif |
| 1154 u.d = value(); | 1177 u.d = value(); |
| 1155 if (u.bits.exp == 2047) { | 1178 if (u.bits.exp == 2047) { |
| 1156 // Detect NaN for IEEE double precision floating point. | 1179 // Detect NaN for IEEE double precision floating point. |
| 1157 if ((u.bits.man_low | u.bits.man_high) != 0) | 1180 if ((u.bits.man_low | u.bits.man_high) != 0) |
| 1158 return Heap::false_value(); | 1181 return GetHeap()->false_value(); |
| 1159 } | 1182 } |
| 1160 if (u.bits.exp == 0) { | 1183 if (u.bits.exp == 0) { |
| 1161 // Detect +0, and -0 for IEEE double precision floating point. | 1184 // Detect +0, and -0 for IEEE double precision floating point. |
| 1162 if ((u.bits.man_low | u.bits.man_high) == 0) | 1185 if ((u.bits.man_low | u.bits.man_high) == 0) |
| 1163 return Heap::false_value(); | 1186 return GetHeap()->false_value(); |
| 1164 } | 1187 } |
| 1165 return Heap::true_value(); | 1188 return GetHeap()->true_value(); |
| 1166 } | 1189 } |
| 1167 | 1190 |
| 1168 | 1191 |
| 1169 void HeapNumber::HeapNumberPrint(FILE* out) { | 1192 void HeapNumber::HeapNumberPrint(FILE* out) { |
| 1170 PrintF(out, "%.16g", Number()); | 1193 PrintF(out, "%.16g", Number()); |
| 1171 } | 1194 } |
| 1172 | 1195 |
| 1173 | 1196 |
| 1174 void HeapNumber::HeapNumberPrint(StringStream* accumulator) { | 1197 void HeapNumber::HeapNumberPrint(StringStream* accumulator) { |
| 1175 // The Windows version of vsnprintf can allocate when printing a %g string | 1198 // The Windows version of vsnprintf can allocate when printing a %g string |
| 1176 // into a buffer that may not be big enough. We don't want random memory | 1199 // into a buffer that may not be big enough. We don't want random memory |
| 1177 // allocation when producing post-crash stack traces, so we print into a | 1200 // allocation when producing post-crash stack traces, so we print into a |
| 1178 // buffer that is plenty big enough for any floating point number, then | 1201 // buffer that is plenty big enough for any floating point number, then |
| 1179 // print that using vsnprintf (which may truncate but never allocate if | 1202 // print that using vsnprintf (which may truncate but never allocate if |
| 1180 // there is no more space in the buffer). | 1203 // there is no more space in the buffer). |
| 1181 EmbeddedVector<char, 100> buffer; | 1204 EmbeddedVector<char, 100> buffer; |
| 1182 OS::SNPrintF(buffer, "%.16g", Number()); | 1205 OS::SNPrintF(buffer, "%.16g", Number()); |
| 1183 accumulator->Add("%s", buffer.start()); | 1206 accumulator->Add("%s", buffer.start()); |
| 1184 } | 1207 } |
| 1185 | 1208 |
| 1186 | 1209 |
| 1187 String* JSObject::class_name() { | 1210 String* JSObject::class_name() { |
| 1188 if (IsJSFunction()) { | 1211 if (IsJSFunction()) { |
| 1189 return Heap::function_class_symbol(); | 1212 return GetHeap()->function_class_symbol(); |
| 1190 } | 1213 } |
| 1191 if (map()->constructor()->IsJSFunction()) { | 1214 if (map()->constructor()->IsJSFunction()) { |
| 1192 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 1215 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 1193 return String::cast(constructor->shared()->instance_class_name()); | 1216 return String::cast(constructor->shared()->instance_class_name()); |
| 1194 } | 1217 } |
| 1195 // If the constructor is not present, return "Object". | 1218 // If the constructor is not present, return "Object". |
| 1196 return Heap::Object_symbol(); | 1219 return GetHeap()->Object_symbol(); |
| 1197 } | 1220 } |
| 1198 | 1221 |
| 1199 | 1222 |
| 1200 String* JSObject::constructor_name() { | 1223 String* JSObject::constructor_name() { |
| 1201 if (map()->constructor()->IsJSFunction()) { | 1224 if (map()->constructor()->IsJSFunction()) { |
| 1202 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 1225 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 1203 String* name = String::cast(constructor->shared()->name()); | 1226 String* name = String::cast(constructor->shared()->name()); |
| 1204 if (name->length() > 0) return name; | 1227 if (name->length() > 0) return name; |
| 1205 String* inferred_name = constructor->shared()->inferred_name(); | 1228 String* inferred_name = constructor->shared()->inferred_name(); |
| 1206 if (inferred_name->length() > 0) return inferred_name; | 1229 if (inferred_name->length() > 0) return inferred_name; |
| 1207 Object* proto = GetPrototype(); | 1230 Object* proto = GetPrototype(); |
| 1208 if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name(); | 1231 if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name(); |
| 1209 } | 1232 } |
| 1210 // If the constructor is not present, return "Object". | 1233 // If the constructor is not present, return "Object". |
| 1211 return Heap::Object_symbol(); | 1234 return GetHeap()->Object_symbol(); |
| 1212 } | 1235 } |
| 1213 | 1236 |
| 1214 | 1237 |
| 1215 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, | 1238 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, |
| 1216 String* name, | 1239 String* name, |
| 1217 Object* value) { | 1240 Object* value) { |
| 1218 int index = new_map->PropertyIndexFor(name); | 1241 int index = new_map->PropertyIndexFor(name); |
| 1219 if (map()->unused_property_fields() == 0) { | 1242 if (map()->unused_property_fields() == 0) { |
| 1220 ASSERT(map()->unused_property_fields() == 0); | 1243 ASSERT(map()->unused_property_fields() == 0); |
| 1221 int new_unused = new_map->unused_property_fields(); | 1244 int new_unused = new_map->unused_property_fields(); |
| 1222 Object* values; | 1245 Object* values; |
| 1223 { MaybeObject* maybe_values = | 1246 { MaybeObject* maybe_values = |
| 1224 properties()->CopySize(properties()->length() + new_unused + 1); | 1247 properties()->CopySize(properties()->length() + new_unused + 1); |
| 1225 if (!maybe_values->ToObject(&values)) return maybe_values; | 1248 if (!maybe_values->ToObject(&values)) return maybe_values; |
| 1226 } | 1249 } |
| 1227 set_properties(FixedArray::cast(values)); | 1250 set_properties(FixedArray::cast(values)); |
| 1228 } | 1251 } |
| 1229 set_map(new_map); | 1252 set_map(new_map); |
| 1230 return FastPropertyAtPut(index, value); | 1253 return FastPropertyAtPut(index, value); |
| 1231 } | 1254 } |
| 1232 | 1255 |
| 1233 | 1256 |
| 1234 MaybeObject* JSObject::AddFastProperty(String* name, | 1257 MaybeObject* JSObject::AddFastProperty(String* name, |
| 1235 Object* value, | 1258 Object* value, |
| 1236 PropertyAttributes attributes) { | 1259 PropertyAttributes attributes) { |
| 1237 ASSERT(!IsJSGlobalProxy()); | 1260 ASSERT(!IsJSGlobalProxy()); |
| 1238 | 1261 |
| 1239 // Normalize the object if the name is an actual string (not the | 1262 // Normalize the object if the name is an actual string (not the |
| 1240 // hidden symbols) and is not a real identifier. | 1263 // hidden symbols) and is not a real identifier. |
| 1264 Isolate* isolate = GetHeap()->isolate(); |
| 1241 StringInputBuffer buffer(name); | 1265 StringInputBuffer buffer(name); |
| 1242 if (!ScannerConstants::IsIdentifier(&buffer) | 1266 if (!isolate->scanner_constants()->IsIdentifier(&buffer) |
| 1243 && name != Heap::hidden_symbol()) { | 1267 && name != HEAP->hidden_symbol()) { |
| 1244 Object* obj; | 1268 Object* obj; |
| 1245 { MaybeObject* maybe_obj = | 1269 { MaybeObject* maybe_obj = |
| 1246 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1270 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 1247 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1271 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1248 } | 1272 } |
| 1249 return AddSlowProperty(name, value, attributes); | 1273 return AddSlowProperty(name, value, attributes); |
| 1250 } | 1274 } |
| 1251 | 1275 |
| 1252 DescriptorArray* old_descriptors = map()->instance_descriptors(); | 1276 DescriptorArray* old_descriptors = map()->instance_descriptors(); |
| 1253 // Compute the new index for new field. | 1277 // Compute the new index for new field. |
| 1254 int index = map()->NextFreePropertyIndex(); | 1278 int index = map()->NextFreePropertyIndex(); |
| 1255 | 1279 |
| 1256 // Allocate new instance descriptors with (name, index) added | 1280 // Allocate new instance descriptors with (name, index) added |
| 1257 FieldDescriptor new_field(name, index, attributes); | 1281 FieldDescriptor new_field(name, index, attributes); |
| 1258 Object* new_descriptors; | 1282 Object* new_descriptors; |
| 1259 { MaybeObject* maybe_new_descriptors = | 1283 { MaybeObject* maybe_new_descriptors = |
| 1260 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); | 1284 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); |
| 1261 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { | 1285 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
| 1262 return maybe_new_descriptors; | 1286 return maybe_new_descriptors; |
| 1263 } | 1287 } |
| 1264 } | 1288 } |
| 1265 | 1289 |
| 1266 // Only allow map transition if the object's map is NOT equal to the | 1290 // Only allow map transition if the object's map is NOT equal to the |
| 1267 // global object_function's map and there is not a transition for name. | 1291 // global object_function's map and there is not a transition for name. |
| 1268 bool allow_map_transition = | 1292 bool allow_map_transition = |
| 1269 !old_descriptors->Contains(name) && | 1293 !old_descriptors->Contains(name) && |
| 1270 (Top::context()->global_context()->object_function()->map() != map()); | 1294 (isolate->context()->global_context()->object_function()-> |
| 1295 map() != map()); |
| 1271 | 1296 |
| 1272 ASSERT(index < map()->inobject_properties() || | 1297 ASSERT(index < map()->inobject_properties() || |
| 1273 (index - map()->inobject_properties()) < properties()->length() || | 1298 (index - map()->inobject_properties()) < properties()->length() || |
| 1274 map()->unused_property_fields() == 0); | 1299 map()->unused_property_fields() == 0); |
| 1275 // Allocate a new map for the object. | 1300 // Allocate a new map for the object. |
| 1276 Object* r; | 1301 Object* r; |
| 1277 { MaybeObject* maybe_r = map()->CopyDropDescriptors(); | 1302 { MaybeObject* maybe_r = map()->CopyDropDescriptors(); |
| 1278 if (!maybe_r->ToObject(&r)) return maybe_r; | 1303 if (!maybe_r->ToObject(&r)) return maybe_r; |
| 1279 } | 1304 } |
| 1280 Map* new_map = Map::cast(r); | 1305 Map* new_map = Map::cast(r); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1314 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | 1339 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
| 1315 set_map(new_map); | 1340 set_map(new_map); |
| 1316 return FastPropertyAtPut(index, value); | 1341 return FastPropertyAtPut(index, value); |
| 1317 } | 1342 } |
| 1318 | 1343 |
| 1319 | 1344 |
| 1320 MaybeObject* JSObject::AddConstantFunctionProperty( | 1345 MaybeObject* JSObject::AddConstantFunctionProperty( |
| 1321 String* name, | 1346 String* name, |
| 1322 JSFunction* function, | 1347 JSFunction* function, |
| 1323 PropertyAttributes attributes) { | 1348 PropertyAttributes attributes) { |
| 1324 ASSERT(!Heap::InNewSpace(function)); | 1349 Heap* heap = GetHeap(); |
| 1350 ASSERT(!heap->InNewSpace(function)); |
| 1325 | 1351 |
| 1326 // Allocate new instance descriptors with (name, function) added | 1352 // Allocate new instance descriptors with (name, function) added |
| 1327 ConstantFunctionDescriptor d(name, function, attributes); | 1353 ConstantFunctionDescriptor d(name, function, attributes); |
| 1328 Object* new_descriptors; | 1354 Object* new_descriptors; |
| 1329 { MaybeObject* maybe_new_descriptors = | 1355 { MaybeObject* maybe_new_descriptors = |
| 1330 map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS); | 1356 map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS); |
| 1331 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { | 1357 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
| 1332 return maybe_new_descriptors; | 1358 return maybe_new_descriptors; |
| 1333 } | 1359 } |
| 1334 } | 1360 } |
| 1335 | 1361 |
| 1336 // Allocate a new map for the object. | 1362 // Allocate a new map for the object. |
| 1337 Object* new_map; | 1363 Object* new_map; |
| 1338 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | 1364 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
| 1339 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 1365 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 1340 } | 1366 } |
| 1341 | 1367 |
| 1342 DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors); | 1368 DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors); |
| 1343 Map::cast(new_map)->set_instance_descriptors(descriptors); | 1369 Map::cast(new_map)->set_instance_descriptors(descriptors); |
| 1344 Map* old_map = map(); | 1370 Map* old_map = map(); |
| 1345 set_map(Map::cast(new_map)); | 1371 set_map(Map::cast(new_map)); |
| 1346 | 1372 |
| 1347 // If the old map is the global object map (from new Object()), | 1373 // If the old map is the global object map (from new Object()), |
| 1348 // then transitions are not added to it, so we are done. | 1374 // then transitions are not added to it, so we are done. |
| 1349 if (old_map == Top::context()->global_context()->object_function()->map()) { | 1375 if (old_map == heap->isolate()->context()->global_context()-> |
| 1376 object_function()->map()) { |
| 1350 return function; | 1377 return function; |
| 1351 } | 1378 } |
| 1352 | 1379 |
| 1353 // Do not add CONSTANT_TRANSITIONS to global objects | 1380 // Do not add CONSTANT_TRANSITIONS to global objects |
| 1354 if (IsGlobalObject()) { | 1381 if (IsGlobalObject()) { |
| 1355 return function; | 1382 return function; |
| 1356 } | 1383 } |
| 1357 | 1384 |
| 1358 // Add a CONSTANT_TRANSITION descriptor to the old map, | 1385 // Add a CONSTANT_TRANSITION descriptor to the old map, |
| 1359 // so future assignments to this property on other objects | 1386 // so future assignments to this property on other objects |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1374 | 1401 |
| 1375 return function; | 1402 return function; |
| 1376 } | 1403 } |
| 1377 | 1404 |
| 1378 | 1405 |
| 1379 // Add property in slow mode | 1406 // Add property in slow mode |
| 1380 MaybeObject* JSObject::AddSlowProperty(String* name, | 1407 MaybeObject* JSObject::AddSlowProperty(String* name, |
| 1381 Object* value, | 1408 Object* value, |
| 1382 PropertyAttributes attributes) { | 1409 PropertyAttributes attributes) { |
| 1383 ASSERT(!HasFastProperties()); | 1410 ASSERT(!HasFastProperties()); |
| 1411 Heap* heap = GetHeap(); |
| 1384 StringDictionary* dict = property_dictionary(); | 1412 StringDictionary* dict = property_dictionary(); |
| 1385 Object* store_value = value; | 1413 Object* store_value = value; |
| 1386 if (IsGlobalObject()) { | 1414 if (IsGlobalObject()) { |
| 1387 // In case name is an orphaned property reuse the cell. | 1415 // In case name is an orphaned property reuse the cell. |
| 1388 int entry = dict->FindEntry(name); | 1416 int entry = dict->FindEntry(name); |
| 1389 if (entry != StringDictionary::kNotFound) { | 1417 if (entry != StringDictionary::kNotFound) { |
| 1390 store_value = dict->ValueAt(entry); | 1418 store_value = dict->ValueAt(entry); |
| 1391 JSGlobalPropertyCell::cast(store_value)->set_value(value); | 1419 JSGlobalPropertyCell::cast(store_value)->set_value(value); |
| 1392 // Assign an enumeration index to the property and update | 1420 // Assign an enumeration index to the property and update |
| 1393 // SetNextEnumerationIndex. | 1421 // SetNextEnumerationIndex. |
| 1394 int index = dict->NextEnumerationIndex(); | 1422 int index = dict->NextEnumerationIndex(); |
| 1395 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); | 1423 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); |
| 1396 dict->SetNextEnumerationIndex(index + 1); | 1424 dict->SetNextEnumerationIndex(index + 1); |
| 1397 dict->SetEntry(entry, name, store_value, details); | 1425 dict->SetEntry(entry, name, store_value, details); |
| 1398 return value; | 1426 return value; |
| 1399 } | 1427 } |
| 1400 { MaybeObject* maybe_store_value = | 1428 { MaybeObject* maybe_store_value = |
| 1401 Heap::AllocateJSGlobalPropertyCell(value); | 1429 heap->AllocateJSGlobalPropertyCell(value); |
| 1402 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; | 1430 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; |
| 1403 } | 1431 } |
| 1404 JSGlobalPropertyCell::cast(store_value)->set_value(value); | 1432 JSGlobalPropertyCell::cast(store_value)->set_value(value); |
| 1405 } | 1433 } |
| 1406 PropertyDetails details = PropertyDetails(attributes, NORMAL); | 1434 PropertyDetails details = PropertyDetails(attributes, NORMAL); |
| 1407 Object* result; | 1435 Object* result; |
| 1408 { MaybeObject* maybe_result = dict->Add(name, store_value, details); | 1436 { MaybeObject* maybe_result = dict->Add(name, store_value, details); |
| 1409 if (!maybe_result->ToObject(&result)) return maybe_result; | 1437 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1410 } | 1438 } |
| 1411 if (dict != result) set_properties(StringDictionary::cast(result)); | 1439 if (dict != result) set_properties(StringDictionary::cast(result)); |
| 1412 return value; | 1440 return value; |
| 1413 } | 1441 } |
| 1414 | 1442 |
| 1415 | 1443 |
| 1416 MaybeObject* JSObject::AddProperty(String* name, | 1444 MaybeObject* JSObject::AddProperty(String* name, |
| 1417 Object* value, | 1445 Object* value, |
| 1418 PropertyAttributes attributes) { | 1446 PropertyAttributes attributes) { |
| 1419 ASSERT(!IsJSGlobalProxy()); | 1447 ASSERT(!IsJSGlobalProxy()); |
| 1448 Heap* heap = GetHeap(); |
| 1420 if (!map()->is_extensible()) { | 1449 if (!map()->is_extensible()) { |
| 1421 Handle<Object> args[1] = {Handle<String>(name)}; | 1450 Handle<Object> args[1] = {Handle<String>(name)}; |
| 1422 return Top::Throw(*Factory::NewTypeError("object_not_extensible", | 1451 return heap->isolate()->Throw( |
| 1423 HandleVector(args, 1))); | 1452 *FACTORY->NewTypeError("object_not_extensible", HandleVector(args, 1))); |
| 1424 } | 1453 } |
| 1425 if (HasFastProperties()) { | 1454 if (HasFastProperties()) { |
| 1426 // Ensure the descriptor array does not get too big. | 1455 // Ensure the descriptor array does not get too big. |
| 1427 if (map()->instance_descriptors()->number_of_descriptors() < | 1456 if (map()->instance_descriptors()->number_of_descriptors() < |
| 1428 DescriptorArray::kMaxNumberOfDescriptors) { | 1457 DescriptorArray::kMaxNumberOfDescriptors) { |
| 1429 if (value->IsJSFunction() && !Heap::InNewSpace(value)) { | 1458 if (value->IsJSFunction() && !heap->InNewSpace(value)) { |
| 1430 return AddConstantFunctionProperty(name, | 1459 return AddConstantFunctionProperty(name, |
| 1431 JSFunction::cast(value), | 1460 JSFunction::cast(value), |
| 1432 attributes); | 1461 attributes); |
| 1433 } else { | 1462 } else { |
| 1434 return AddFastProperty(name, value, attributes); | 1463 return AddFastProperty(name, value, attributes); |
| 1435 } | 1464 } |
| 1436 } else { | 1465 } else { |
| 1437 // Normalize the object to prevent very large instance descriptors. | 1466 // Normalize the object to prevent very large instance descriptors. |
| 1438 // This eliminates unwanted N^2 allocation and lookup behavior. | 1467 // This eliminates unwanted N^2 allocation and lookup behavior. |
| 1439 Object* obj; | 1468 Object* obj; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1491 { MaybeObject* maybe_result = | 1520 { MaybeObject* maybe_result = |
| 1492 ConvertDescriptorToField(name, new_value, attributes); | 1521 ConvertDescriptorToField(name, new_value, attributes); |
| 1493 if (!maybe_result->ToObject(&result)) return maybe_result; | 1522 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1494 } | 1523 } |
| 1495 // If we get to this point we have succeeded - do not return failure | 1524 // If we get to this point we have succeeded - do not return failure |
| 1496 // after this point. Later stuff is optional. | 1525 // after this point. Later stuff is optional. |
| 1497 if (!HasFastProperties()) { | 1526 if (!HasFastProperties()) { |
| 1498 return result; | 1527 return result; |
| 1499 } | 1528 } |
| 1500 // Do not add transitions to the map of "new Object()". | 1529 // Do not add transitions to the map of "new Object()". |
| 1501 if (map() == Top::context()->global_context()->object_function()->map()) { | 1530 if (map() == GetHeap()->isolate()->context()->global_context()-> |
| 1531 object_function()->map()) { |
| 1502 return result; | 1532 return result; |
| 1503 } | 1533 } |
| 1504 | 1534 |
| 1505 MapTransitionDescriptor transition(name, | 1535 MapTransitionDescriptor transition(name, |
| 1506 map(), | 1536 map(), |
| 1507 attributes); | 1537 attributes); |
| 1508 Object* new_descriptors; | 1538 Object* new_descriptors; |
| 1509 { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()-> | 1539 { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()-> |
| 1510 CopyInsert(&transition, KEEP_TRANSITIONS); | 1540 CopyInsert(&transition, KEEP_TRANSITIONS); |
| 1511 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { | 1541 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1578 return FastPropertyAtPut(index, new_value); | 1608 return FastPropertyAtPut(index, new_value); |
| 1579 } | 1609 } |
| 1580 | 1610 |
| 1581 | 1611 |
| 1582 | 1612 |
| 1583 MaybeObject* JSObject::SetPropertyWithInterceptor( | 1613 MaybeObject* JSObject::SetPropertyWithInterceptor( |
| 1584 String* name, | 1614 String* name, |
| 1585 Object* value, | 1615 Object* value, |
| 1586 PropertyAttributes attributes, | 1616 PropertyAttributes attributes, |
| 1587 StrictModeFlag strict_mode) { | 1617 StrictModeFlag strict_mode) { |
| 1588 HandleScope scope; | 1618 Isolate* isolate = GetIsolate(); |
| 1619 HandleScope scope(isolate); |
| 1589 Handle<JSObject> this_handle(this); | 1620 Handle<JSObject> this_handle(this); |
| 1590 Handle<String> name_handle(name); | 1621 Handle<String> name_handle(name); |
| 1591 Handle<Object> value_handle(value); | 1622 Handle<Object> value_handle(value, isolate); |
| 1592 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 1623 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 1593 if (!interceptor->setter()->IsUndefined()) { | 1624 if (!interceptor->setter()->IsUndefined()) { |
| 1594 LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name)); | 1625 LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); |
| 1595 CustomArguments args(interceptor->data(), this, this); | 1626 CustomArguments args(isolate, interceptor->data(), this, this); |
| 1596 v8::AccessorInfo info(args.end()); | 1627 v8::AccessorInfo info(args.end()); |
| 1597 v8::NamedPropertySetter setter = | 1628 v8::NamedPropertySetter setter = |
| 1598 v8::ToCData<v8::NamedPropertySetter>(interceptor->setter()); | 1629 v8::ToCData<v8::NamedPropertySetter>(interceptor->setter()); |
| 1599 v8::Handle<v8::Value> result; | 1630 v8::Handle<v8::Value> result; |
| 1600 { | 1631 { |
| 1601 // Leaving JavaScript. | 1632 // Leaving JavaScript. |
| 1602 VMState state(EXTERNAL); | 1633 VMState state(isolate, EXTERNAL); |
| 1603 Handle<Object> value_unhole(value->IsTheHole() ? | 1634 Handle<Object> value_unhole(value->IsTheHole() ? |
| 1604 Heap::undefined_value() : | 1635 isolate->heap()->undefined_value() : |
| 1605 value); | 1636 value, |
| 1637 isolate); |
| 1606 result = setter(v8::Utils::ToLocal(name_handle), | 1638 result = setter(v8::Utils::ToLocal(name_handle), |
| 1607 v8::Utils::ToLocal(value_unhole), | 1639 v8::Utils::ToLocal(value_unhole), |
| 1608 info); | 1640 info); |
| 1609 } | 1641 } |
| 1610 RETURN_IF_SCHEDULED_EXCEPTION(); | 1642 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1611 if (!result.IsEmpty()) return *value_handle; | 1643 if (!result.IsEmpty()) return *value_handle; |
| 1612 } | 1644 } |
| 1613 MaybeObject* raw_result = | 1645 MaybeObject* raw_result = |
| 1614 this_handle->SetPropertyPostInterceptor(*name_handle, | 1646 this_handle->SetPropertyPostInterceptor(*name_handle, |
| 1615 *value_handle, | 1647 *value_handle, |
| 1616 attributes, | 1648 attributes, |
| 1617 strict_mode); | 1649 strict_mode); |
| 1618 RETURN_IF_SCHEDULED_EXCEPTION(); | 1650 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1619 return raw_result; | 1651 return raw_result; |
| 1620 } | 1652 } |
| 1621 | 1653 |
| 1622 | 1654 |
| 1623 MaybeObject* JSObject::SetProperty(String* name, | 1655 MaybeObject* JSObject::SetProperty(String* name, |
| 1624 Object* value, | 1656 Object* value, |
| 1625 PropertyAttributes attributes, | 1657 PropertyAttributes attributes, |
| 1626 StrictModeFlag strict_mode) { | 1658 StrictModeFlag strict_mode) { |
| 1627 LookupResult result; | 1659 LookupResult result; |
| 1628 LocalLookup(name, &result); | 1660 LocalLookup(name, &result); |
| 1629 return SetProperty(&result, name, value, attributes, strict_mode); | 1661 return SetProperty(&result, name, value, attributes, strict_mode); |
| 1630 } | 1662 } |
| 1631 | 1663 |
| 1632 | 1664 |
| 1633 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, | 1665 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, |
| 1634 String* name, | 1666 String* name, |
| 1635 Object* value, | 1667 Object* value, |
| 1636 JSObject* holder) { | 1668 JSObject* holder) { |
| 1637 HandleScope scope; | 1669 Isolate* isolate = GetIsolate(); |
| 1670 HandleScope scope(isolate); |
| 1638 | 1671 |
| 1639 // We should never get here to initialize a const with the hole | 1672 // We should never get here to initialize a const with the hole |
| 1640 // value since a const declaration would conflict with the setter. | 1673 // value since a const declaration would conflict with the setter. |
| 1641 ASSERT(!value->IsTheHole()); | 1674 ASSERT(!value->IsTheHole()); |
| 1642 Handle<Object> value_handle(value); | 1675 Handle<Object> value_handle(value, isolate); |
| 1643 | 1676 |
| 1644 // To accommodate both the old and the new api we switch on the | 1677 // To accommodate both the old and the new api we switch on the |
| 1645 // data structure used to store the callbacks. Eventually proxy | 1678 // data structure used to store the callbacks. Eventually proxy |
| 1646 // callbacks should be phased out. | 1679 // callbacks should be phased out. |
| 1647 if (structure->IsProxy()) { | 1680 if (structure->IsProxy()) { |
| 1648 AccessorDescriptor* callback = | 1681 AccessorDescriptor* callback = |
| 1649 reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); | 1682 reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); |
| 1650 MaybeObject* obj = (callback->setter)(this, value, callback->data); | 1683 MaybeObject* obj = (callback->setter)(this, value, callback->data); |
| 1651 RETURN_IF_SCHEDULED_EXCEPTION(); | 1684 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1652 if (obj->IsFailure()) return obj; | 1685 if (obj->IsFailure()) return obj; |
| 1653 return *value_handle; | 1686 return *value_handle; |
| 1654 } | 1687 } |
| 1655 | 1688 |
| 1656 if (structure->IsAccessorInfo()) { | 1689 if (structure->IsAccessorInfo()) { |
| 1657 // api style callbacks | 1690 // api style callbacks |
| 1658 AccessorInfo* data = AccessorInfo::cast(structure); | 1691 AccessorInfo* data = AccessorInfo::cast(structure); |
| 1659 Object* call_obj = data->setter(); | 1692 Object* call_obj = data->setter(); |
| 1660 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); | 1693 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); |
| 1661 if (call_fun == NULL) return value; | 1694 if (call_fun == NULL) return value; |
| 1662 Handle<String> key(name); | 1695 Handle<String> key(name); |
| 1663 LOG(ApiNamedPropertyAccess("store", this, name)); | 1696 LOG(isolate, ApiNamedPropertyAccess("store", this, name)); |
| 1664 CustomArguments args(data->data(), this, JSObject::cast(holder)); | 1697 CustomArguments args(isolate, data->data(), this, JSObject::cast(holder)); |
| 1665 v8::AccessorInfo info(args.end()); | 1698 v8::AccessorInfo info(args.end()); |
| 1666 { | 1699 { |
| 1667 // Leaving JavaScript. | 1700 // Leaving JavaScript. |
| 1668 VMState state(EXTERNAL); | 1701 VMState state(isolate, EXTERNAL); |
| 1669 call_fun(v8::Utils::ToLocal(key), | 1702 call_fun(v8::Utils::ToLocal(key), |
| 1670 v8::Utils::ToLocal(value_handle), | 1703 v8::Utils::ToLocal(value_handle), |
| 1671 info); | 1704 info); |
| 1672 } | 1705 } |
| 1673 RETURN_IF_SCHEDULED_EXCEPTION(); | 1706 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1674 return *value_handle; | 1707 return *value_handle; |
| 1675 } | 1708 } |
| 1676 | 1709 |
| 1677 if (structure->IsFixedArray()) { | 1710 if (structure->IsFixedArray()) { |
| 1678 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); | 1711 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); |
| 1679 if (setter->IsJSFunction()) { | 1712 if (setter->IsJSFunction()) { |
| 1680 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); | 1713 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); |
| 1681 } else { | 1714 } else { |
| 1682 Handle<String> key(name); | 1715 Handle<String> key(name); |
| 1683 Handle<Object> holder_handle(holder); | 1716 Handle<Object> holder_handle(holder, isolate); |
| 1684 Handle<Object> args[2] = { key, holder_handle }; | 1717 Handle<Object> args[2] = { key, holder_handle }; |
| 1685 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback", | 1718 return isolate->Throw( |
| 1686 HandleVector(args, 2))); | 1719 *isolate->factory()->NewTypeError("no_setter_in_callback", |
| 1720 HandleVector(args, 2))); |
| 1687 } | 1721 } |
| 1688 } | 1722 } |
| 1689 | 1723 |
| 1690 UNREACHABLE(); | 1724 UNREACHABLE(); |
| 1691 return NULL; | 1725 return NULL; |
| 1692 } | 1726 } |
| 1693 | 1727 |
| 1694 | 1728 |
| 1695 MaybeObject* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter, | 1729 MaybeObject* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter, |
| 1696 Object* value) { | 1730 Object* value) { |
| 1697 Handle<Object> value_handle(value); | 1731 Isolate* isolate = GetIsolate(); |
| 1698 Handle<JSFunction> fun(JSFunction::cast(setter)); | 1732 Handle<Object> value_handle(value, isolate); |
| 1699 Handle<JSObject> self(this); | 1733 Handle<JSFunction> fun(JSFunction::cast(setter), isolate); |
| 1734 Handle<JSObject> self(this, isolate); |
| 1700 #ifdef ENABLE_DEBUGGER_SUPPORT | 1735 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 1736 Debug* debug = isolate->debug(); |
| 1701 // Handle stepping into a setter if step into is active. | 1737 // Handle stepping into a setter if step into is active. |
| 1702 if (Debug::StepInActive()) { | 1738 if (debug->StepInActive()) { |
| 1703 Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false); | 1739 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false); |
| 1704 } | 1740 } |
| 1705 #endif | 1741 #endif |
| 1706 bool has_pending_exception; | 1742 bool has_pending_exception; |
| 1707 Object** argv[] = { value_handle.location() }; | 1743 Object** argv[] = { value_handle.location() }; |
| 1708 Execution::Call(fun, self, 1, argv, &has_pending_exception); | 1744 Execution::Call(fun, self, 1, argv, &has_pending_exception); |
| 1709 // Check for pending exception and return the result. | 1745 // Check for pending exception and return the result. |
| 1710 if (has_pending_exception) return Failure::Exception(); | 1746 if (has_pending_exception) return Failure::Exception(); |
| 1711 return *value_handle; | 1747 return *value_handle; |
| 1712 } | 1748 } |
| 1713 | 1749 |
| 1714 | 1750 |
| 1715 void JSObject::LookupCallbackSetterInPrototypes(String* name, | 1751 void JSObject::LookupCallbackSetterInPrototypes(String* name, |
| 1716 LookupResult* result) { | 1752 LookupResult* result) { |
| 1753 Heap* heap = GetHeap(); |
| 1717 for (Object* pt = GetPrototype(); | 1754 for (Object* pt = GetPrototype(); |
| 1718 pt != Heap::null_value(); | 1755 pt != heap->null_value(); |
| 1719 pt = pt->GetPrototype()) { | 1756 pt = pt->GetPrototype()) { |
| 1720 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 1757 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 1721 if (result->IsProperty()) { | 1758 if (result->IsProperty()) { |
| 1722 if (result->IsReadOnly()) { | 1759 if (result->IsReadOnly()) { |
| 1723 result->NotFound(); | 1760 result->NotFound(); |
| 1724 return; | 1761 return; |
| 1725 } | 1762 } |
| 1726 if (result->type() == CALLBACKS) { | 1763 if (result->type() == CALLBACKS) { |
| 1727 return; | 1764 return; |
| 1728 } | 1765 } |
| 1729 } | 1766 } |
| 1730 } | 1767 } |
| 1731 result->NotFound(); | 1768 result->NotFound(); |
| 1732 } | 1769 } |
| 1733 | 1770 |
| 1734 | 1771 |
| 1735 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index, | 1772 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index, |
| 1736 Object* value, | 1773 Object* value, |
| 1737 bool* found) { | 1774 bool* found) { |
| 1775 Heap* heap = GetHeap(); |
| 1738 for (Object* pt = GetPrototype(); | 1776 for (Object* pt = GetPrototype(); |
| 1739 pt != Heap::null_value(); | 1777 pt != heap->null_value(); |
| 1740 pt = pt->GetPrototype()) { | 1778 pt = pt->GetPrototype()) { |
| 1741 if (!JSObject::cast(pt)->HasDictionaryElements()) { | 1779 if (!JSObject::cast(pt)->HasDictionaryElements()) { |
| 1742 continue; | 1780 continue; |
| 1743 } | 1781 } |
| 1744 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); | 1782 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); |
| 1745 int entry = dictionary->FindEntry(index); | 1783 int entry = dictionary->FindEntry(index); |
| 1746 if (entry != NumberDictionary::kNotFound) { | 1784 if (entry != NumberDictionary::kNotFound) { |
| 1747 PropertyDetails details = dictionary->DetailsAt(entry); | 1785 PropertyDetails details = dictionary->DetailsAt(entry); |
| 1748 if (details.type() == CALLBACKS) { | 1786 if (details.type() == CALLBACKS) { |
| 1749 *found = true; | 1787 *found = true; |
| 1750 return SetElementWithCallback( | 1788 return SetElementWithCallback( |
| 1751 dictionary->ValueAt(entry), index, value, JSObject::cast(pt)); | 1789 dictionary->ValueAt(entry), index, value, JSObject::cast(pt)); |
| 1752 } | 1790 } |
| 1753 } | 1791 } |
| 1754 } | 1792 } |
| 1755 *found = false; | 1793 *found = false; |
| 1756 return Heap::the_hole_value(); | 1794 return heap->the_hole_value(); |
| 1757 } | 1795 } |
| 1758 | 1796 |
| 1759 | 1797 |
| 1760 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { | 1798 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { |
| 1761 DescriptorArray* descriptors = map()->instance_descriptors(); | 1799 DescriptorArray* descriptors = map()->instance_descriptors(); |
| 1762 int number = descriptors->SearchWithCache(name); | 1800 int number = descriptors->SearchWithCache(name); |
| 1763 if (number != DescriptorArray::kNotFound) { | 1801 if (number != DescriptorArray::kNotFound) { |
| 1764 result->DescriptorResult(this, descriptors->GetDetails(number), number); | 1802 result->DescriptorResult(this, descriptors->GetDetails(number), number); |
| 1765 } else { | 1803 } else { |
| 1766 result->NotFound(); | 1804 result->NotFound(); |
| 1767 } | 1805 } |
| 1768 } | 1806 } |
| 1769 | 1807 |
| 1770 | 1808 |
| 1771 void Map::LookupInDescriptors(JSObject* holder, | 1809 void Map::LookupInDescriptors(JSObject* holder, |
| 1772 String* name, | 1810 String* name, |
| 1773 LookupResult* result) { | 1811 LookupResult* result) { |
| 1774 DescriptorArray* descriptors = instance_descriptors(); | 1812 DescriptorArray* descriptors = instance_descriptors(); |
| 1775 int number = DescriptorLookupCache::Lookup(descriptors, name); | 1813 DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache(); |
| 1814 int number = cache->Lookup(descriptors, name); |
| 1776 if (number == DescriptorLookupCache::kAbsent) { | 1815 if (number == DescriptorLookupCache::kAbsent) { |
| 1777 number = descriptors->Search(name); | 1816 number = descriptors->Search(name); |
| 1778 DescriptorLookupCache::Update(descriptors, name, number); | 1817 cache->Update(descriptors, name, number); |
| 1779 } | 1818 } |
| 1780 if (number != DescriptorArray::kNotFound) { | 1819 if (number != DescriptorArray::kNotFound) { |
| 1781 result->DescriptorResult(holder, descriptors->GetDetails(number), number); | 1820 result->DescriptorResult(holder, descriptors->GetDetails(number), number); |
| 1782 } else { | 1821 } else { |
| 1783 result->NotFound(); | 1822 result->NotFound(); |
| 1784 } | 1823 } |
| 1785 } | 1824 } |
| 1786 | 1825 |
| 1787 | 1826 |
| 1788 void JSObject::LocalLookupRealNamedProperty(String* name, | 1827 void JSObject::LocalLookupRealNamedProperty(String* name, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1836 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) { | 1875 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) { |
| 1837 LocalLookupRealNamedProperty(name, result); | 1876 LocalLookupRealNamedProperty(name, result); |
| 1838 if (result->IsProperty()) return; | 1877 if (result->IsProperty()) return; |
| 1839 | 1878 |
| 1840 LookupRealNamedPropertyInPrototypes(name, result); | 1879 LookupRealNamedPropertyInPrototypes(name, result); |
| 1841 } | 1880 } |
| 1842 | 1881 |
| 1843 | 1882 |
| 1844 void JSObject::LookupRealNamedPropertyInPrototypes(String* name, | 1883 void JSObject::LookupRealNamedPropertyInPrototypes(String* name, |
| 1845 LookupResult* result) { | 1884 LookupResult* result) { |
| 1885 Heap* heap = GetHeap(); |
| 1846 for (Object* pt = GetPrototype(); | 1886 for (Object* pt = GetPrototype(); |
| 1847 pt != Heap::null_value(); | 1887 pt != heap->null_value(); |
| 1848 pt = JSObject::cast(pt)->GetPrototype()) { | 1888 pt = JSObject::cast(pt)->GetPrototype()) { |
| 1849 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 1889 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 1850 if (result->IsProperty() && (result->type() != INTERCEPTOR)) return; | 1890 if (result->IsProperty() && (result->type() != INTERCEPTOR)) return; |
| 1851 } | 1891 } |
| 1852 result->NotFound(); | 1892 result->NotFound(); |
| 1853 } | 1893 } |
| 1854 | 1894 |
| 1855 | 1895 |
| 1856 // We only need to deal with CALLBACKS and INTERCEPTORS | 1896 // We only need to deal with CALLBACKS and INTERCEPTORS |
| 1857 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, | 1897 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, |
| 1858 String* name, | 1898 String* name, |
| 1859 Object* value, | 1899 Object* value, |
| 1860 bool check_prototype) { | 1900 bool check_prototype) { |
| 1901 Heap* heap = GetHeap(); |
| 1861 if (check_prototype && !result->IsProperty()) { | 1902 if (check_prototype && !result->IsProperty()) { |
| 1862 LookupCallbackSetterInPrototypes(name, result); | 1903 LookupCallbackSetterInPrototypes(name, result); |
| 1863 } | 1904 } |
| 1864 | 1905 |
| 1865 if (result->IsProperty()) { | 1906 if (result->IsProperty()) { |
| 1866 if (!result->IsReadOnly()) { | 1907 if (!result->IsReadOnly()) { |
| 1867 switch (result->type()) { | 1908 switch (result->type()) { |
| 1868 case CALLBACKS: { | 1909 case CALLBACKS: { |
| 1869 Object* obj = result->GetCallbackObject(); | 1910 Object* obj = result->GetCallbackObject(); |
| 1870 if (obj->IsAccessorInfo()) { | 1911 if (obj->IsAccessorInfo()) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1891 } | 1932 } |
| 1892 default: { | 1933 default: { |
| 1893 break; | 1934 break; |
| 1894 } | 1935 } |
| 1895 } | 1936 } |
| 1896 } | 1937 } |
| 1897 } | 1938 } |
| 1898 | 1939 |
| 1899 HandleScope scope; | 1940 HandleScope scope; |
| 1900 Handle<Object> value_handle(value); | 1941 Handle<Object> value_handle(value); |
| 1901 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 1942 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 1902 return *value_handle; | 1943 return *value_handle; |
| 1903 } | 1944 } |
| 1904 | 1945 |
| 1905 | 1946 |
| 1906 MaybeObject* JSObject::SetProperty(LookupResult* result, | 1947 MaybeObject* JSObject::SetProperty(LookupResult* result, |
| 1907 String* name, | 1948 String* name, |
| 1908 Object* value, | 1949 Object* value, |
| 1909 PropertyAttributes attributes, | 1950 PropertyAttributes attributes, |
| 1910 StrictModeFlag strict_mode) { | 1951 StrictModeFlag strict_mode) { |
| 1952 Heap* heap = GetHeap(); |
| 1911 // Make sure that the top context does not change when doing callbacks or | 1953 // Make sure that the top context does not change when doing callbacks or |
| 1912 // interceptor calls. | 1954 // interceptor calls. |
| 1913 AssertNoContextChange ncc; | 1955 AssertNoContextChange ncc; |
| 1914 | 1956 |
| 1915 // Optimization for 2-byte strings often used as keys in a decompression | 1957 // Optimization for 2-byte strings often used as keys in a decompression |
| 1916 // dictionary. We make these short keys into symbols to avoid constantly | 1958 // dictionary. We make these short keys into symbols to avoid constantly |
| 1917 // reallocating them. | 1959 // reallocating them. |
| 1918 if (!name->IsSymbol() && name->length() <= 2) { | 1960 if (!name->IsSymbol() && name->length() <= 2) { |
| 1919 Object* symbol_version; | 1961 Object* symbol_version; |
| 1920 { MaybeObject* maybe_symbol_version = Heap::LookupSymbol(name); | 1962 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name); |
| 1921 if (maybe_symbol_version->ToObject(&symbol_version)) { | 1963 if (maybe_symbol_version->ToObject(&symbol_version)) { |
| 1922 name = String::cast(symbol_version); | 1964 name = String::cast(symbol_version); |
| 1923 } | 1965 } |
| 1924 } | 1966 } |
| 1925 } | 1967 } |
| 1926 | 1968 |
| 1927 // Check access rights if needed. | 1969 // Check access rights if needed. |
| 1928 if (IsAccessCheckNeeded() | 1970 if (IsAccessCheckNeeded() |
| 1929 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 1971 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 1930 return SetPropertyWithFailedAccessCheck(result, name, value, true); | 1972 return SetPropertyWithFailedAccessCheck(result, name, value, true); |
| 1931 } | 1973 } |
| 1932 | 1974 |
| 1933 if (IsJSGlobalProxy()) { | 1975 if (IsJSGlobalProxy()) { |
| 1934 Object* proto = GetPrototype(); | 1976 Object* proto = GetPrototype(); |
| 1935 if (proto->IsNull()) return value; | 1977 if (proto->IsNull()) return value; |
| 1936 ASSERT(proto->IsJSGlobalObject()); | 1978 ASSERT(proto->IsJSGlobalObject()); |
| 1937 return JSObject::cast(proto)->SetProperty( | 1979 return JSObject::cast(proto)->SetProperty( |
| 1938 result, name, value, attributes, strict_mode); | 1980 result, name, value, attributes, strict_mode); |
| 1939 } | 1981 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1953 if (!result->IsFound()) { | 1995 if (!result->IsFound()) { |
| 1954 // Neither properties nor transitions found. | 1996 // Neither properties nor transitions found. |
| 1955 return AddProperty(name, value, attributes); | 1997 return AddProperty(name, value, attributes); |
| 1956 } | 1998 } |
| 1957 if (result->IsReadOnly() && result->IsProperty()) { | 1999 if (result->IsReadOnly() && result->IsProperty()) { |
| 1958 if (strict_mode == kStrictMode) { | 2000 if (strict_mode == kStrictMode) { |
| 1959 HandleScope scope; | 2001 HandleScope scope; |
| 1960 Handle<String> key(name); | 2002 Handle<String> key(name); |
| 1961 Handle<Object> holder(this); | 2003 Handle<Object> holder(this); |
| 1962 Handle<Object> args[2] = { key, holder }; | 2004 Handle<Object> args[2] = { key, holder }; |
| 1963 return Top::Throw(*Factory::NewTypeError("strict_read_only_property", | 2005 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( |
| 1964 HandleVector(args, 2))); | 2006 "strict_read_only_property", HandleVector(args, 2))); |
| 1965 } else { | 2007 } else { |
| 1966 return value; | 2008 return value; |
| 1967 } | 2009 } |
| 1968 } | 2010 } |
| 1969 // This is a real property that is not read-only, or it is a | 2011 // This is a real property that is not read-only, or it is a |
| 1970 // transition or null descriptor and there are no setters in the prototypes. | 2012 // transition or null descriptor and there are no setters in the prototypes. |
| 1971 switch (result->type()) { | 2013 switch (result->type()) { |
| 1972 case NORMAL: | 2014 case NORMAL: |
| 1973 return SetNormalizedProperty(result, value); | 2015 return SetNormalizedProperty(result, value); |
| 1974 case FIELD: | 2016 case FIELD: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1997 case CONSTANT_TRANSITION: { | 2039 case CONSTANT_TRANSITION: { |
| 1998 // If the same constant function is being added we can simply | 2040 // If the same constant function is being added we can simply |
| 1999 // transition to the target map. | 2041 // transition to the target map. |
| 2000 Map* target_map = result->GetTransitionMap(); | 2042 Map* target_map = result->GetTransitionMap(); |
| 2001 DescriptorArray* target_descriptors = target_map->instance_descriptors(); | 2043 DescriptorArray* target_descriptors = target_map->instance_descriptors(); |
| 2002 int number = target_descriptors->SearchWithCache(name); | 2044 int number = target_descriptors->SearchWithCache(name); |
| 2003 ASSERT(number != DescriptorArray::kNotFound); | 2045 ASSERT(number != DescriptorArray::kNotFound); |
| 2004 ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION); | 2046 ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION); |
| 2005 JSFunction* function = | 2047 JSFunction* function = |
| 2006 JSFunction::cast(target_descriptors->GetValue(number)); | 2048 JSFunction::cast(target_descriptors->GetValue(number)); |
| 2007 ASSERT(!Heap::InNewSpace(function)); | 2049 ASSERT(!HEAP->InNewSpace(function)); |
| 2008 if (value == function) { | 2050 if (value == function) { |
| 2009 set_map(target_map); | 2051 set_map(target_map); |
| 2010 return value; | 2052 return value; |
| 2011 } | 2053 } |
| 2012 // Otherwise, replace with a MAP_TRANSITION to a new map with a | 2054 // Otherwise, replace with a MAP_TRANSITION to a new map with a |
| 2013 // FIELD, even if the value is a constant function. | 2055 // FIELD, even if the value is a constant function. |
| 2014 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); | 2056 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
| 2015 } | 2057 } |
| 2016 case NULL_DESCRIPTOR: | 2058 case NULL_DESCRIPTOR: |
| 2017 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); | 2059 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
| 2018 default: | 2060 default: |
| 2019 UNREACHABLE(); | 2061 UNREACHABLE(); |
| 2020 } | 2062 } |
| 2021 UNREACHABLE(); | 2063 UNREACHABLE(); |
| 2022 return value; | 2064 return value; |
| 2023 } | 2065 } |
| 2024 | 2066 |
| 2025 | 2067 |
| 2026 // Set a real local property, even if it is READ_ONLY. If the property is not | 2068 // Set a real local property, even if it is READ_ONLY. If the property is not |
| 2027 // present, add it with attributes NONE. This code is an exact clone of | 2069 // present, add it with attributes NONE. This code is an exact clone of |
| 2028 // SetProperty, with the check for IsReadOnly and the check for a | 2070 // SetProperty, with the check for IsReadOnly and the check for a |
| 2029 // callback setter removed. The two lines looking up the LookupResult | 2071 // callback setter removed. The two lines looking up the LookupResult |
| 2030 // result are also added. If one of the functions is changed, the other | 2072 // result are also added. If one of the functions is changed, the other |
| 2031 // should be. | 2073 // should be. |
| 2032 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( | 2074 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
| 2033 String* name, | 2075 String* name, |
| 2034 Object* value, | 2076 Object* value, |
| 2035 PropertyAttributes attributes) { | 2077 PropertyAttributes attributes) { |
| 2078 Heap* heap = GetHeap(); |
| 2079 |
| 2036 // Make sure that the top context does not change when doing callbacks or | 2080 // Make sure that the top context does not change when doing callbacks or |
| 2037 // interceptor calls. | 2081 // interceptor calls. |
| 2038 AssertNoContextChange ncc; | 2082 AssertNoContextChange ncc; |
| 2039 LookupResult result; | 2083 LookupResult result; |
| 2040 LocalLookup(name, &result); | 2084 LocalLookup(name, &result); |
| 2041 // Check access rights if needed. | 2085 // Check access rights if needed. |
| 2042 if (IsAccessCheckNeeded() | 2086 if (IsAccessCheckNeeded() |
| 2043 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 2087 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 2044 return SetPropertyWithFailedAccessCheck(&result, name, value, false); | 2088 return SetPropertyWithFailedAccessCheck(&result, name, value, false); |
| 2045 } | 2089 } |
| 2046 | 2090 |
| 2047 if (IsJSGlobalProxy()) { | 2091 if (IsJSGlobalProxy()) { |
| 2048 Object* proto = GetPrototype(); | 2092 Object* proto = GetPrototype(); |
| 2049 if (proto->IsNull()) return value; | 2093 if (proto->IsNull()) return value; |
| 2050 ASSERT(proto->IsJSGlobalObject()); | 2094 ASSERT(proto->IsJSGlobalObject()); |
| 2051 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( | 2095 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( |
| 2052 name, | 2096 name, |
| 2053 value, | 2097 value, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2105 String* name, | 2149 String* name, |
| 2106 bool continue_search) { | 2150 bool continue_search) { |
| 2107 // Check local property, ignore interceptor. | 2151 // Check local property, ignore interceptor. |
| 2108 LookupResult result; | 2152 LookupResult result; |
| 2109 LocalLookupRealNamedProperty(name, &result); | 2153 LocalLookupRealNamedProperty(name, &result); |
| 2110 if (result.IsProperty()) return result.GetAttributes(); | 2154 if (result.IsProperty()) return result.GetAttributes(); |
| 2111 | 2155 |
| 2112 if (continue_search) { | 2156 if (continue_search) { |
| 2113 // Continue searching via the prototype chain. | 2157 // Continue searching via the prototype chain. |
| 2114 Object* pt = GetPrototype(); | 2158 Object* pt = GetPrototype(); |
| 2115 if (pt != Heap::null_value()) { | 2159 if (!pt->IsNull()) { |
| 2116 return JSObject::cast(pt)-> | 2160 return JSObject::cast(pt)-> |
| 2117 GetPropertyAttributeWithReceiver(receiver, name); | 2161 GetPropertyAttributeWithReceiver(receiver, name); |
| 2118 } | 2162 } |
| 2119 } | 2163 } |
| 2120 return ABSENT; | 2164 return ABSENT; |
| 2121 } | 2165 } |
| 2122 | 2166 |
| 2123 | 2167 |
| 2124 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( | 2168 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( |
| 2125 JSObject* receiver, | 2169 JSObject* receiver, |
| 2126 String* name, | 2170 String* name, |
| 2127 bool continue_search) { | 2171 bool continue_search) { |
| 2172 Isolate* isolate = GetIsolate(); |
| 2173 |
| 2128 // Make sure that the top context does not change when doing | 2174 // Make sure that the top context does not change when doing |
| 2129 // callbacks or interceptor calls. | 2175 // callbacks or interceptor calls. |
| 2130 AssertNoContextChange ncc; | 2176 AssertNoContextChange ncc; |
| 2131 | 2177 |
| 2132 HandleScope scope; | 2178 HandleScope scope(isolate); |
| 2133 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 2179 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 2134 Handle<JSObject> receiver_handle(receiver); | 2180 Handle<JSObject> receiver_handle(receiver); |
| 2135 Handle<JSObject> holder_handle(this); | 2181 Handle<JSObject> holder_handle(this); |
| 2136 Handle<String> name_handle(name); | 2182 Handle<String> name_handle(name); |
| 2137 CustomArguments args(interceptor->data(), receiver, this); | 2183 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 2138 v8::AccessorInfo info(args.end()); | 2184 v8::AccessorInfo info(args.end()); |
| 2139 if (!interceptor->query()->IsUndefined()) { | 2185 if (!interceptor->query()->IsUndefined()) { |
| 2140 v8::NamedPropertyQuery query = | 2186 v8::NamedPropertyQuery query = |
| 2141 v8::ToCData<v8::NamedPropertyQuery>(interceptor->query()); | 2187 v8::ToCData<v8::NamedPropertyQuery>(interceptor->query()); |
| 2142 LOG(ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name)); | 2188 LOG(isolate, |
| 2189 ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name)); |
| 2143 v8::Handle<v8::Integer> result; | 2190 v8::Handle<v8::Integer> result; |
| 2144 { | 2191 { |
| 2145 // Leaving JavaScript. | 2192 // Leaving JavaScript. |
| 2146 VMState state(EXTERNAL); | 2193 VMState state(isolate, EXTERNAL); |
| 2147 result = query(v8::Utils::ToLocal(name_handle), info); | 2194 result = query(v8::Utils::ToLocal(name_handle), info); |
| 2148 } | 2195 } |
| 2149 if (!result.IsEmpty()) { | 2196 if (!result.IsEmpty()) { |
| 2150 ASSERT(result->IsInt32()); | 2197 ASSERT(result->IsInt32()); |
| 2151 return static_cast<PropertyAttributes>(result->Int32Value()); | 2198 return static_cast<PropertyAttributes>(result->Int32Value()); |
| 2152 } | 2199 } |
| 2153 } else if (!interceptor->getter()->IsUndefined()) { | 2200 } else if (!interceptor->getter()->IsUndefined()) { |
| 2154 v8::NamedPropertyGetter getter = | 2201 v8::NamedPropertyGetter getter = |
| 2155 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); | 2202 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); |
| 2156 LOG(ApiNamedPropertyAccess("interceptor-named-get-has", this, name)); | 2203 LOG(isolate, |
| 2204 ApiNamedPropertyAccess("interceptor-named-get-has", this, name)); |
| 2157 v8::Handle<v8::Value> result; | 2205 v8::Handle<v8::Value> result; |
| 2158 { | 2206 { |
| 2159 // Leaving JavaScript. | 2207 // Leaving JavaScript. |
| 2160 VMState state(EXTERNAL); | 2208 VMState state(isolate, EXTERNAL); |
| 2161 result = getter(v8::Utils::ToLocal(name_handle), info); | 2209 result = getter(v8::Utils::ToLocal(name_handle), info); |
| 2162 } | 2210 } |
| 2163 if (!result.IsEmpty()) return DONT_ENUM; | 2211 if (!result.IsEmpty()) return DONT_ENUM; |
| 2164 } | 2212 } |
| 2165 return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle, | 2213 return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle, |
| 2166 *name_handle, | 2214 *name_handle, |
| 2167 continue_search); | 2215 continue_search); |
| 2168 } | 2216 } |
| 2169 | 2217 |
| 2170 | 2218 |
| 2171 PropertyAttributes JSObject::GetPropertyAttributeWithReceiver( | 2219 PropertyAttributes JSObject::GetPropertyAttributeWithReceiver( |
| 2172 JSObject* receiver, | 2220 JSObject* receiver, |
| 2173 String* key) { | 2221 String* key) { |
| 2174 uint32_t index = 0; | 2222 uint32_t index = 0; |
| 2175 if (key->AsArrayIndex(&index)) { | 2223 if (key->AsArrayIndex(&index)) { |
| 2176 if (HasElementWithReceiver(receiver, index)) return NONE; | 2224 if (HasElementWithReceiver(receiver, index)) return NONE; |
| 2177 return ABSENT; | 2225 return ABSENT; |
| 2178 } | 2226 } |
| 2179 // Named property. | 2227 // Named property. |
| 2180 LookupResult result; | 2228 LookupResult result; |
| 2181 Lookup(key, &result); | 2229 Lookup(key, &result); |
| 2182 return GetPropertyAttribute(receiver, &result, key, true); | 2230 return GetPropertyAttribute(receiver, &result, key, true); |
| 2183 } | 2231 } |
| 2184 | 2232 |
| 2185 | 2233 |
| 2186 PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, | 2234 PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, |
| 2187 LookupResult* result, | 2235 LookupResult* result, |
| 2188 String* name, | 2236 String* name, |
| 2189 bool continue_search) { | 2237 bool continue_search) { |
| 2238 Heap* heap = GetHeap(); |
| 2190 // Check access rights if needed. | 2239 // Check access rights if needed. |
| 2191 if (IsAccessCheckNeeded() && | 2240 if (IsAccessCheckNeeded() && |
| 2192 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) { | 2241 !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { |
| 2193 return GetPropertyAttributeWithFailedAccessCheck(receiver, | 2242 return GetPropertyAttributeWithFailedAccessCheck(receiver, |
| 2194 result, | 2243 result, |
| 2195 name, | 2244 name, |
| 2196 continue_search); | 2245 continue_search); |
| 2197 } | 2246 } |
| 2198 if (result->IsProperty()) { | 2247 if (result->IsProperty()) { |
| 2199 switch (result->type()) { | 2248 switch (result->type()) { |
| 2200 case NORMAL: // fall through | 2249 case NORMAL: // fall through |
| 2201 case FIELD: | 2250 case FIELD: |
| 2202 case CONSTANT_FUNCTION: | 2251 case CONSTANT_FUNCTION: |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2248 } | 2297 } |
| 2249 #endif | 2298 #endif |
| 2250 return result; | 2299 return result; |
| 2251 } | 2300 } |
| 2252 | 2301 |
| 2253 { MaybeObject* maybe_result = | 2302 { MaybeObject* maybe_result = |
| 2254 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); | 2303 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); |
| 2255 if (!maybe_result->ToObject(&result)) return maybe_result; | 2304 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2256 } | 2305 } |
| 2257 set(index, result); | 2306 set(index, result); |
| 2258 Counters::normalized_maps.Increment(); | 2307 COUNTERS->normalized_maps()->Increment(); |
| 2259 | 2308 |
| 2260 return result; | 2309 return result; |
| 2261 } | 2310 } |
| 2262 | 2311 |
| 2263 | 2312 |
| 2264 void NormalizedMapCache::Clear() { | 2313 void NormalizedMapCache::Clear() { |
| 2265 int entries = length(); | 2314 int entries = length(); |
| 2266 for (int i = 0; i != entries; i++) { | 2315 for (int i = 0; i != entries; i++) { |
| 2267 set_undefined(i); | 2316 set_undefined(i); |
| 2268 } | 2317 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2308 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) { | 2357 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) { |
| 2309 if (map()->is_shared()) { | 2358 if (map()->is_shared()) { |
| 2310 // Fast case maps are never marked as shared. | 2359 // Fast case maps are never marked as shared. |
| 2311 ASSERT(!HasFastProperties()); | 2360 ASSERT(!HasFastProperties()); |
| 2312 // Replace the map with an identical copy that can be safely modified. | 2361 // Replace the map with an identical copy that can be safely modified. |
| 2313 Object* obj; | 2362 Object* obj; |
| 2314 { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, | 2363 { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, |
| 2315 UNIQUE_NORMALIZED_MAP); | 2364 UNIQUE_NORMALIZED_MAP); |
| 2316 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2365 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2317 } | 2366 } |
| 2318 Counters::normalized_maps.Increment(); | 2367 COUNTERS->normalized_maps()->Increment(); |
| 2319 | 2368 |
| 2320 set_map(Map::cast(obj)); | 2369 set_map(Map::cast(obj)); |
| 2321 } | 2370 } |
| 2322 return map()->UpdateCodeCache(name, code); | 2371 return map()->UpdateCodeCache(name, code); |
| 2323 } | 2372 } |
| 2324 | 2373 |
| 2325 | 2374 |
| 2326 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, | 2375 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, |
| 2327 int expected_additional_properties) { | 2376 int expected_additional_properties) { |
| 2328 if (!HasFastProperties()) return this; | 2377 if (!HasFastProperties()) return this; |
| 2329 | 2378 |
| 2330 // The global object is always normalized. | 2379 // The global object is always normalized. |
| 2331 ASSERT(!IsGlobalObject()); | 2380 ASSERT(!IsGlobalObject()); |
| 2332 | |
| 2333 // JSGlobalProxy must never be normalized | 2381 // JSGlobalProxy must never be normalized |
| 2334 ASSERT(!IsJSGlobalProxy()); | 2382 ASSERT(!IsJSGlobalProxy()); |
| 2335 | 2383 |
| 2384 Heap* heap = GetHeap(); |
| 2385 |
| 2336 // Allocate new content. | 2386 // Allocate new content. |
| 2337 int property_count = map()->NumberOfDescribedProperties(); | 2387 int property_count = map()->NumberOfDescribedProperties(); |
| 2338 if (expected_additional_properties > 0) { | 2388 if (expected_additional_properties > 0) { |
| 2339 property_count += expected_additional_properties; | 2389 property_count += expected_additional_properties; |
| 2340 } else { | 2390 } else { |
| 2341 property_count += 2; // Make space for two more properties. | 2391 property_count += 2; // Make space for two more properties. |
| 2342 } | 2392 } |
| 2343 Object* obj; | 2393 Object* obj; |
| 2344 { MaybeObject* maybe_obj = | 2394 { MaybeObject* maybe_obj = |
| 2345 StringDictionary::Allocate(property_count); | 2395 StringDictionary::Allocate(property_count); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2394 break; | 2444 break; |
| 2395 default: | 2445 default: |
| 2396 UNREACHABLE(); | 2446 UNREACHABLE(); |
| 2397 } | 2447 } |
| 2398 } | 2448 } |
| 2399 | 2449 |
| 2400 // Copy the next enumeration index from instance descriptor. | 2450 // Copy the next enumeration index from instance descriptor. |
| 2401 int index = map()->instance_descriptors()->NextEnumerationIndex(); | 2451 int index = map()->instance_descriptors()->NextEnumerationIndex(); |
| 2402 dictionary->SetNextEnumerationIndex(index); | 2452 dictionary->SetNextEnumerationIndex(index); |
| 2403 | 2453 |
| 2404 { MaybeObject* maybe_obj = Top::context()->global_context()-> | 2454 { MaybeObject* maybe_obj = heap->isolate()->context()->global_context()-> |
| 2405 normalized_map_cache()->Get(this, mode); | 2455 normalized_map_cache()->Get(this, mode); |
| 2406 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2456 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2407 } | 2457 } |
| 2408 Map* new_map = Map::cast(obj); | 2458 Map* new_map = Map::cast(obj); |
| 2409 | 2459 |
| 2410 // We have now successfully allocated all the necessary objects. | 2460 // We have now successfully allocated all the necessary objects. |
| 2411 // Changes can now be made with the guarantee that all of them take effect. | 2461 // Changes can now be made with the guarantee that all of them take effect. |
| 2412 | 2462 |
| 2413 // Resize the object in the heap if necessary. | 2463 // Resize the object in the heap if necessary. |
| 2414 int new_instance_size = new_map->instance_size(); | 2464 int new_instance_size = new_map->instance_size(); |
| 2415 int instance_size_delta = map()->instance_size() - new_instance_size; | 2465 int instance_size_delta = map()->instance_size() - new_instance_size; |
| 2416 ASSERT(instance_size_delta >= 0); | 2466 ASSERT(instance_size_delta >= 0); |
| 2417 Heap::CreateFillerObjectAt(this->address() + new_instance_size, | 2467 heap->CreateFillerObjectAt(this->address() + new_instance_size, |
| 2418 instance_size_delta); | 2468 instance_size_delta); |
| 2419 | 2469 |
| 2420 set_map(new_map); | 2470 set_map(new_map); |
| 2471 map()->set_instance_descriptors(heap->empty_descriptor_array()); |
| 2421 | 2472 |
| 2422 set_properties(dictionary); | 2473 set_properties(dictionary); |
| 2423 | 2474 |
| 2424 Counters::props_to_dictionary.Increment(); | 2475 heap->isolate()->counters()->props_to_dictionary()->Increment(); |
| 2425 | 2476 |
| 2426 #ifdef DEBUG | 2477 #ifdef DEBUG |
| 2427 if (FLAG_trace_normalization) { | 2478 if (FLAG_trace_normalization) { |
| 2428 PrintF("Object properties have been normalized:\n"); | 2479 PrintF("Object properties have been normalized:\n"); |
| 2429 Print(); | 2480 Print(); |
| 2430 } | 2481 } |
| 2431 #endif | 2482 #endif |
| 2432 return this; | 2483 return this; |
| 2433 } | 2484 } |
| 2434 | 2485 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2475 } | 2526 } |
| 2476 dictionary = NumberDictionary::cast(result); | 2527 dictionary = NumberDictionary::cast(result); |
| 2477 } | 2528 } |
| 2478 } | 2529 } |
| 2479 // Switch to using the dictionary as the backing storage for | 2530 // Switch to using the dictionary as the backing storage for |
| 2480 // elements. Set the new map first to satify the elements type | 2531 // elements. Set the new map first to satify the elements type |
| 2481 // assert in set_elements(). | 2532 // assert in set_elements(). |
| 2482 set_map(new_map); | 2533 set_map(new_map); |
| 2483 set_elements(dictionary); | 2534 set_elements(dictionary); |
| 2484 | 2535 |
| 2485 Counters::elements_to_dictionary.Increment(); | 2536 new_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> |
| 2537 Increment(); |
| 2486 | 2538 |
| 2487 #ifdef DEBUG | 2539 #ifdef DEBUG |
| 2488 if (FLAG_trace_normalization) { | 2540 if (FLAG_trace_normalization) { |
| 2489 PrintF("Object elements have been normalized:\n"); | 2541 PrintF("Object elements have been normalized:\n"); |
| 2490 Print(); | 2542 Print(); |
| 2491 } | 2543 } |
| 2492 #endif | 2544 #endif |
| 2493 | 2545 |
| 2494 return this; | 2546 return this; |
| 2495 } | 2547 } |
| 2496 | 2548 |
| 2497 | 2549 |
| 2498 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, | 2550 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, |
| 2499 DeleteMode mode) { | 2551 DeleteMode mode) { |
| 2500 // Check local property, ignore interceptor. | 2552 // Check local property, ignore interceptor. |
| 2553 Heap* heap = GetHeap(); |
| 2501 LookupResult result; | 2554 LookupResult result; |
| 2502 LocalLookupRealNamedProperty(name, &result); | 2555 LocalLookupRealNamedProperty(name, &result); |
| 2503 if (!result.IsProperty()) return Heap::true_value(); | 2556 if (!result.IsProperty()) return heap->true_value(); |
| 2504 | 2557 |
| 2505 // Normalize object if needed. | 2558 // Normalize object if needed. |
| 2506 Object* obj; | 2559 Object* obj; |
| 2507 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2560 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2508 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2561 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2509 } | 2562 } |
| 2510 | 2563 |
| 2511 return DeleteNormalizedProperty(name, mode); | 2564 return DeleteNormalizedProperty(name, mode); |
| 2512 } | 2565 } |
| 2513 | 2566 |
| 2514 | 2567 |
| 2515 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) { | 2568 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) { |
| 2516 HandleScope scope; | 2569 Isolate* isolate = GetIsolate(); |
| 2570 HandleScope scope(isolate); |
| 2517 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 2571 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 2518 Handle<String> name_handle(name); | 2572 Handle<String> name_handle(name); |
| 2519 Handle<JSObject> this_handle(this); | 2573 Handle<JSObject> this_handle(this); |
| 2520 if (!interceptor->deleter()->IsUndefined()) { | 2574 if (!interceptor->deleter()->IsUndefined()) { |
| 2521 v8::NamedPropertyDeleter deleter = | 2575 v8::NamedPropertyDeleter deleter = |
| 2522 v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter()); | 2576 v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter()); |
| 2523 LOG(ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name)); | 2577 LOG(isolate, |
| 2524 CustomArguments args(interceptor->data(), this, this); | 2578 ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name)); |
| 2579 CustomArguments args(isolate, interceptor->data(), this, this); |
| 2525 v8::AccessorInfo info(args.end()); | 2580 v8::AccessorInfo info(args.end()); |
| 2526 v8::Handle<v8::Boolean> result; | 2581 v8::Handle<v8::Boolean> result; |
| 2527 { | 2582 { |
| 2528 // Leaving JavaScript. | 2583 // Leaving JavaScript. |
| 2529 VMState state(EXTERNAL); | 2584 VMState state(isolate, EXTERNAL); |
| 2530 result = deleter(v8::Utils::ToLocal(name_handle), info); | 2585 result = deleter(v8::Utils::ToLocal(name_handle), info); |
| 2531 } | 2586 } |
| 2532 RETURN_IF_SCHEDULED_EXCEPTION(); | 2587 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2533 if (!result.IsEmpty()) { | 2588 if (!result.IsEmpty()) { |
| 2534 ASSERT(result->IsBoolean()); | 2589 ASSERT(result->IsBoolean()); |
| 2535 return *v8::Utils::OpenHandle(*result); | 2590 return *v8::Utils::OpenHandle(*result); |
| 2536 } | 2591 } |
| 2537 } | 2592 } |
| 2538 MaybeObject* raw_result = | 2593 MaybeObject* raw_result = |
| 2539 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); | 2594 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); |
| 2540 RETURN_IF_SCHEDULED_EXCEPTION(); | 2595 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2541 return raw_result; | 2596 return raw_result; |
| 2542 } | 2597 } |
| 2543 | 2598 |
| 2544 | 2599 |
| 2545 MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, | 2600 MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, |
| 2546 DeleteMode mode) { | 2601 DeleteMode mode) { |
| 2602 Heap* heap = GetHeap(); |
| 2547 ASSERT(!HasExternalArrayElements()); | 2603 ASSERT(!HasExternalArrayElements()); |
| 2548 switch (GetElementsKind()) { | 2604 switch (GetElementsKind()) { |
| 2549 case FAST_ELEMENTS: { | 2605 case FAST_ELEMENTS: { |
| 2550 Object* obj; | 2606 Object* obj; |
| 2551 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 2607 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 2552 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2608 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2553 } | 2609 } |
| 2554 uint32_t length = IsJSArray() ? | 2610 uint32_t length = IsJSArray() ? |
| 2555 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : | 2611 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : |
| 2556 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 2612 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 2557 if (index < length) { | 2613 if (index < length) { |
| 2558 FixedArray::cast(elements())->set_the_hole(index); | 2614 FixedArray::cast(elements())->set_the_hole(index); |
| 2559 } | 2615 } |
| 2560 break; | 2616 break; |
| 2561 } | 2617 } |
| 2562 case DICTIONARY_ELEMENTS: { | 2618 case DICTIONARY_ELEMENTS: { |
| 2563 NumberDictionary* dictionary = element_dictionary(); | 2619 NumberDictionary* dictionary = element_dictionary(); |
| 2564 int entry = dictionary->FindEntry(index); | 2620 int entry = dictionary->FindEntry(index); |
| 2565 if (entry != NumberDictionary::kNotFound) { | 2621 if (entry != NumberDictionary::kNotFound) { |
| 2566 return dictionary->DeleteProperty(entry, mode); | 2622 return dictionary->DeleteProperty(entry, mode); |
| 2567 } | 2623 } |
| 2568 break; | 2624 break; |
| 2569 } | 2625 } |
| 2570 default: | 2626 default: |
| 2571 UNREACHABLE(); | 2627 UNREACHABLE(); |
| 2572 break; | 2628 break; |
| 2573 } | 2629 } |
| 2574 return Heap::true_value(); | 2630 return heap->true_value(); |
| 2575 } | 2631 } |
| 2576 | 2632 |
| 2577 | 2633 |
| 2578 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { | 2634 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { |
| 2635 Isolate* isolate = GetIsolate(); |
| 2636 Heap* heap = isolate->heap(); |
| 2579 // Make sure that the top context does not change when doing | 2637 // Make sure that the top context does not change when doing |
| 2580 // callbacks or interceptor calls. | 2638 // callbacks or interceptor calls. |
| 2581 AssertNoContextChange ncc; | 2639 AssertNoContextChange ncc; |
| 2582 HandleScope scope; | 2640 HandleScope scope(isolate); |
| 2583 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 2641 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 2584 if (interceptor->deleter()->IsUndefined()) return Heap::false_value(); | 2642 if (interceptor->deleter()->IsUndefined()) return heap->false_value(); |
| 2585 v8::IndexedPropertyDeleter deleter = | 2643 v8::IndexedPropertyDeleter deleter = |
| 2586 v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter()); | 2644 v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter()); |
| 2587 Handle<JSObject> this_handle(this); | 2645 Handle<JSObject> this_handle(this); |
| 2588 LOG(ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index)); | 2646 LOG(isolate, |
| 2589 CustomArguments args(interceptor->data(), this, this); | 2647 ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index)); |
| 2648 CustomArguments args(isolate, interceptor->data(), this, this); |
| 2590 v8::AccessorInfo info(args.end()); | 2649 v8::AccessorInfo info(args.end()); |
| 2591 v8::Handle<v8::Boolean> result; | 2650 v8::Handle<v8::Boolean> result; |
| 2592 { | 2651 { |
| 2593 // Leaving JavaScript. | 2652 // Leaving JavaScript. |
| 2594 VMState state(EXTERNAL); | 2653 VMState state(isolate, EXTERNAL); |
| 2595 result = deleter(index, info); | 2654 result = deleter(index, info); |
| 2596 } | 2655 } |
| 2597 RETURN_IF_SCHEDULED_EXCEPTION(); | 2656 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2598 if (!result.IsEmpty()) { | 2657 if (!result.IsEmpty()) { |
| 2599 ASSERT(result->IsBoolean()); | 2658 ASSERT(result->IsBoolean()); |
| 2600 return *v8::Utils::OpenHandle(*result); | 2659 return *v8::Utils::OpenHandle(*result); |
| 2601 } | 2660 } |
| 2602 MaybeObject* raw_result = | 2661 MaybeObject* raw_result = |
| 2603 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); | 2662 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); |
| 2604 RETURN_IF_SCHEDULED_EXCEPTION(); | 2663 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2605 return raw_result; | 2664 return raw_result; |
| 2606 } | 2665 } |
| 2607 | 2666 |
| 2608 | 2667 |
| 2609 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { | 2668 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { |
| 2669 Isolate* isolate = GetIsolate(); |
| 2610 // Check access rights if needed. | 2670 // Check access rights if needed. |
| 2611 if (IsAccessCheckNeeded() && | 2671 if (IsAccessCheckNeeded() && |
| 2612 !Top::MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { | 2672 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { |
| 2613 Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE); | 2673 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); |
| 2614 return Heap::false_value(); | 2674 return isolate->heap()->false_value(); |
| 2615 } | 2675 } |
| 2616 | 2676 |
| 2617 if (IsJSGlobalProxy()) { | 2677 if (IsJSGlobalProxy()) { |
| 2618 Object* proto = GetPrototype(); | 2678 Object* proto = GetPrototype(); |
| 2619 if (proto->IsNull()) return Heap::false_value(); | 2679 if (proto->IsNull()) return isolate->heap()->false_value(); |
| 2620 ASSERT(proto->IsJSGlobalObject()); | 2680 ASSERT(proto->IsJSGlobalObject()); |
| 2621 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); | 2681 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); |
| 2622 } | 2682 } |
| 2623 | 2683 |
| 2624 if (HasIndexedInterceptor()) { | 2684 if (HasIndexedInterceptor()) { |
| 2625 // Skip interceptor if forcing deletion. | 2685 // Skip interceptor if forcing deletion. |
| 2626 if (mode == FORCE_DELETION) { | 2686 if (mode == FORCE_DELETION) { |
| 2627 return DeleteElementPostInterceptor(index, mode); | 2687 return DeleteElementPostInterceptor(index, mode); |
| 2628 } | 2688 } |
| 2629 return DeleteElementWithInterceptor(index); | 2689 return DeleteElementWithInterceptor(index); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2652 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2712 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 2653 case EXTERNAL_FLOAT_ELEMENTS: | 2713 case EXTERNAL_FLOAT_ELEMENTS: |
| 2654 // Pixel and external array elements cannot be deleted. Just | 2714 // Pixel and external array elements cannot be deleted. Just |
| 2655 // silently ignore here. | 2715 // silently ignore here. |
| 2656 break; | 2716 break; |
| 2657 case DICTIONARY_ELEMENTS: { | 2717 case DICTIONARY_ELEMENTS: { |
| 2658 NumberDictionary* dictionary = element_dictionary(); | 2718 NumberDictionary* dictionary = element_dictionary(); |
| 2659 int entry = dictionary->FindEntry(index); | 2719 int entry = dictionary->FindEntry(index); |
| 2660 if (entry != NumberDictionary::kNotFound) { | 2720 if (entry != NumberDictionary::kNotFound) { |
| 2661 Object* result = dictionary->DeleteProperty(entry, mode); | 2721 Object* result = dictionary->DeleteProperty(entry, mode); |
| 2662 if (mode == STRICT_DELETION && result == Heap::false_value()) { | 2722 if (mode == STRICT_DELETION && result == |
| 2723 isolate->heap()->false_value()) { |
| 2663 // In strict mode, deleting a non-configurable property throws | 2724 // In strict mode, deleting a non-configurable property throws |
| 2664 // exception. dictionary->DeleteProperty will return false_value() | 2725 // exception. dictionary->DeleteProperty will return false_value() |
| 2665 // if a non-configurable property is being deleted. | 2726 // if a non-configurable property is being deleted. |
| 2666 HandleScope scope; | 2727 HandleScope scope; |
| 2667 Handle<Object> i = Factory::NewNumberFromUint(index); | 2728 Handle<Object> i = isolate->factory()->NewNumberFromUint(index); |
| 2668 Handle<Object> args[2] = { i, Handle<Object>(this) }; | 2729 Handle<Object> args[2] = { i, Handle<Object>(this) }; |
| 2669 return Top::Throw(*Factory::NewTypeError("strict_delete_property", | 2730 return isolate->Throw(*isolate->factory()->NewTypeError( |
| 2670 HandleVector(args, 2))); | 2731 "strict_delete_property", HandleVector(args, 2))); |
| 2671 } | 2732 } |
| 2672 } | 2733 } |
| 2673 break; | 2734 break; |
| 2674 } | 2735 } |
| 2675 default: | 2736 default: |
| 2676 UNREACHABLE(); | 2737 UNREACHABLE(); |
| 2677 break; | 2738 break; |
| 2678 } | 2739 } |
| 2679 return Heap::true_value(); | 2740 return isolate->heap()->true_value(); |
| 2680 } | 2741 } |
| 2681 | 2742 |
| 2682 | 2743 |
| 2683 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { | 2744 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { |
| 2745 Isolate* isolate = GetIsolate(); |
| 2684 // ECMA-262, 3rd, 8.6.2.5 | 2746 // ECMA-262, 3rd, 8.6.2.5 |
| 2685 ASSERT(name->IsString()); | 2747 ASSERT(name->IsString()); |
| 2686 | 2748 |
| 2687 // Check access rights if needed. | 2749 // Check access rights if needed. |
| 2688 if (IsAccessCheckNeeded() && | 2750 if (IsAccessCheckNeeded() && |
| 2689 !Top::MayNamedAccess(this, name, v8::ACCESS_DELETE)) { | 2751 !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) { |
| 2690 Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE); | 2752 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); |
| 2691 return Heap::false_value(); | 2753 return isolate->heap()->false_value(); |
| 2692 } | 2754 } |
| 2693 | 2755 |
| 2694 if (IsJSGlobalProxy()) { | 2756 if (IsJSGlobalProxy()) { |
| 2695 Object* proto = GetPrototype(); | 2757 Object* proto = GetPrototype(); |
| 2696 if (proto->IsNull()) return Heap::false_value(); | 2758 if (proto->IsNull()) return isolate->heap()->false_value(); |
| 2697 ASSERT(proto->IsJSGlobalObject()); | 2759 ASSERT(proto->IsJSGlobalObject()); |
| 2698 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); | 2760 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); |
| 2699 } | 2761 } |
| 2700 | 2762 |
| 2701 uint32_t index = 0; | 2763 uint32_t index = 0; |
| 2702 if (name->AsArrayIndex(&index)) { | 2764 if (name->AsArrayIndex(&index)) { |
| 2703 return DeleteElement(index, mode); | 2765 return DeleteElement(index, mode); |
| 2704 } else { | 2766 } else { |
| 2705 LookupResult result; | 2767 LookupResult result; |
| 2706 LocalLookup(name, &result); | 2768 LocalLookup(name, &result); |
| 2707 if (!result.IsProperty()) return Heap::true_value(); | 2769 if (!result.IsProperty()) return isolate->heap()->true_value(); |
| 2708 // Ignore attributes if forcing a deletion. | 2770 // Ignore attributes if forcing a deletion. |
| 2709 if (result.IsDontDelete() && mode != FORCE_DELETION) { | 2771 if (result.IsDontDelete() && mode != FORCE_DELETION) { |
| 2710 if (mode == STRICT_DELETION) { | 2772 if (mode == STRICT_DELETION) { |
| 2711 // Deleting a non-configurable property in strict mode. | 2773 // Deleting a non-configurable property in strict mode. |
| 2712 HandleScope scope; | 2774 HandleScope scope(isolate); |
| 2713 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; | 2775 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; |
| 2714 return Top::Throw(*Factory::NewTypeError("strict_delete_property", | 2776 return isolate->Throw(*isolate->factory()->NewTypeError( |
| 2715 HandleVector(args, 2))); | 2777 "strict_delete_property", HandleVector(args, 2))); |
| 2716 } | 2778 } |
| 2717 return Heap::false_value(); | 2779 return isolate->heap()->false_value(); |
| 2718 } | 2780 } |
| 2719 // Check for interceptor. | 2781 // Check for interceptor. |
| 2720 if (result.type() == INTERCEPTOR) { | 2782 if (result.type() == INTERCEPTOR) { |
| 2721 // Skip interceptor if forcing a deletion. | 2783 // Skip interceptor if forcing a deletion. |
| 2722 if (mode == FORCE_DELETION) { | 2784 if (mode == FORCE_DELETION) { |
| 2723 return DeletePropertyPostInterceptor(name, mode); | 2785 return DeletePropertyPostInterceptor(name, mode); |
| 2724 } | 2786 } |
| 2725 return DeletePropertyWithInterceptor(name); | 2787 return DeletePropertyWithInterceptor(name); |
| 2726 } | 2788 } |
| 2727 // Normalize object if needed. | 2789 // Normalize object if needed. |
| 2728 Object* obj; | 2790 Object* obj; |
| 2729 { MaybeObject* maybe_obj = | 2791 { MaybeObject* maybe_obj = |
| 2730 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2792 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2731 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2793 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2732 } | 2794 } |
| 2733 // Make sure the properties are normalized before removing the entry. | 2795 // Make sure the properties are normalized before removing the entry. |
| 2734 return DeleteNormalizedProperty(name, mode); | 2796 return DeleteNormalizedProperty(name, mode); |
| 2735 } | 2797 } |
| 2736 } | 2798 } |
| 2737 | 2799 |
| 2738 | 2800 |
| 2739 // Check whether this object references another object. | 2801 // Check whether this object references another object. |
| 2740 bool JSObject::ReferencesObject(Object* obj) { | 2802 bool JSObject::ReferencesObject(Object* obj) { |
| 2803 Heap* heap = GetHeap(); |
| 2741 AssertNoAllocation no_alloc; | 2804 AssertNoAllocation no_alloc; |
| 2742 | 2805 |
| 2743 // Is the object the constructor for this object? | 2806 // Is the object the constructor for this object? |
| 2744 if (map()->constructor() == obj) { | 2807 if (map()->constructor() == obj) { |
| 2745 return true; | 2808 return true; |
| 2746 } | 2809 } |
| 2747 | 2810 |
| 2748 // Is the object the prototype for this object? | 2811 // Is the object the prototype for this object? |
| 2749 if (map()->prototype() == obj) { | 2812 if (map()->prototype() == obj) { |
| 2750 return true; | 2813 return true; |
| 2751 } | 2814 } |
| 2752 | 2815 |
| 2753 // Check if the object is among the named properties. | 2816 // Check if the object is among the named properties. |
| 2754 Object* key = SlowReverseLookup(obj); | 2817 Object* key = SlowReverseLookup(obj); |
| 2755 if (key != Heap::undefined_value()) { | 2818 if (!key->IsUndefined()) { |
| 2756 return true; | 2819 return true; |
| 2757 } | 2820 } |
| 2758 | 2821 |
| 2759 // Check if the object is among the indexed properties. | 2822 // Check if the object is among the indexed properties. |
| 2760 switch (GetElementsKind()) { | 2823 switch (GetElementsKind()) { |
| 2761 case EXTERNAL_PIXEL_ELEMENTS: | 2824 case EXTERNAL_PIXEL_ELEMENTS: |
| 2762 case EXTERNAL_BYTE_ELEMENTS: | 2825 case EXTERNAL_BYTE_ELEMENTS: |
| 2763 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 2826 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 2764 case EXTERNAL_SHORT_ELEMENTS: | 2827 case EXTERNAL_SHORT_ELEMENTS: |
| 2765 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 2828 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2776 for (int i = 0; i < length; i++) { | 2839 for (int i = 0; i < length; i++) { |
| 2777 Object* element = FixedArray::cast(elements())->get(i); | 2840 Object* element = FixedArray::cast(elements())->get(i); |
| 2778 if (!element->IsTheHole() && element == obj) { | 2841 if (!element->IsTheHole() && element == obj) { |
| 2779 return true; | 2842 return true; |
| 2780 } | 2843 } |
| 2781 } | 2844 } |
| 2782 break; | 2845 break; |
| 2783 } | 2846 } |
| 2784 case DICTIONARY_ELEMENTS: { | 2847 case DICTIONARY_ELEMENTS: { |
| 2785 key = element_dictionary()->SlowReverseLookup(obj); | 2848 key = element_dictionary()->SlowReverseLookup(obj); |
| 2786 if (key != Heap::undefined_value()) { | 2849 if (!key->IsUndefined()) { |
| 2787 return true; | 2850 return true; |
| 2788 } | 2851 } |
| 2789 break; | 2852 break; |
| 2790 } | 2853 } |
| 2791 default: | 2854 default: |
| 2792 UNREACHABLE(); | 2855 UNREACHABLE(); |
| 2793 break; | 2856 break; |
| 2794 } | 2857 } |
| 2795 | 2858 |
| 2796 // For functions check the context. | 2859 // For functions check the context. |
| 2797 if (IsJSFunction()) { | 2860 if (IsJSFunction()) { |
| 2798 // Get the constructor function for arguments array. | 2861 // Get the constructor function for arguments array. |
| 2799 JSObject* arguments_boilerplate = | 2862 JSObject* arguments_boilerplate = |
| 2800 Top::context()->global_context()->arguments_boilerplate(); | 2863 heap->isolate()->context()->global_context()-> |
| 2864 arguments_boilerplate(); |
| 2801 JSFunction* arguments_function = | 2865 JSFunction* arguments_function = |
| 2802 JSFunction::cast(arguments_boilerplate->map()->constructor()); | 2866 JSFunction::cast(arguments_boilerplate->map()->constructor()); |
| 2803 | 2867 |
| 2804 // Get the context and don't check if it is the global context. | 2868 // Get the context and don't check if it is the global context. |
| 2805 JSFunction* f = JSFunction::cast(this); | 2869 JSFunction* f = JSFunction::cast(this); |
| 2806 Context* context = f->context(); | 2870 Context* context = f->context(); |
| 2807 if (context->IsGlobalContext()) { | 2871 if (context->IsGlobalContext()) { |
| 2808 return false; | 2872 return false; |
| 2809 } | 2873 } |
| 2810 | 2874 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2829 return context->extension()->ReferencesObject(obj); | 2893 return context->extension()->ReferencesObject(obj); |
| 2830 } | 2894 } |
| 2831 } | 2895 } |
| 2832 | 2896 |
| 2833 // No references to object. | 2897 // No references to object. |
| 2834 return false; | 2898 return false; |
| 2835 } | 2899 } |
| 2836 | 2900 |
| 2837 | 2901 |
| 2838 MaybeObject* JSObject::PreventExtensions() { | 2902 MaybeObject* JSObject::PreventExtensions() { |
| 2903 Isolate* isolate = GetIsolate(); |
| 2839 if (IsAccessCheckNeeded() && | 2904 if (IsAccessCheckNeeded() && |
| 2840 !Top::MayNamedAccess(this, Heap::undefined_value(), v8::ACCESS_KEYS)) { | 2905 !isolate->MayNamedAccess(this, |
| 2841 Top::ReportFailedAccessCheck(this, v8::ACCESS_KEYS); | 2906 isolate->heap()->undefined_value(), |
| 2842 return Heap::false_value(); | 2907 v8::ACCESS_KEYS)) { |
| 2908 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); |
| 2909 return isolate->heap()->false_value(); |
| 2843 } | 2910 } |
| 2844 | 2911 |
| 2845 if (IsJSGlobalProxy()) { | 2912 if (IsJSGlobalProxy()) { |
| 2846 Object* proto = GetPrototype(); | 2913 Object* proto = GetPrototype(); |
| 2847 if (proto->IsNull()) return this; | 2914 if (proto->IsNull()) return this; |
| 2848 ASSERT(proto->IsJSGlobalObject()); | 2915 ASSERT(proto->IsJSGlobalObject()); |
| 2849 return JSObject::cast(proto)->PreventExtensions(); | 2916 return JSObject::cast(proto)->PreventExtensions(); |
| 2850 } | 2917 } |
| 2851 | 2918 |
| 2852 // If there are fast elements we normalize. | 2919 // If there are fast elements we normalize. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2871 return new_map; | 2938 return new_map; |
| 2872 } | 2939 } |
| 2873 | 2940 |
| 2874 | 2941 |
| 2875 // Tests for the fast common case for property enumeration: | 2942 // Tests for the fast common case for property enumeration: |
| 2876 // - This object and all prototypes has an enum cache (which means that it has | 2943 // - This object and all prototypes has an enum cache (which means that it has |
| 2877 // no interceptors and needs no access checks). | 2944 // no interceptors and needs no access checks). |
| 2878 // - This object has no elements. | 2945 // - This object has no elements. |
| 2879 // - No prototype has enumerable properties/elements. | 2946 // - No prototype has enumerable properties/elements. |
| 2880 bool JSObject::IsSimpleEnum() { | 2947 bool JSObject::IsSimpleEnum() { |
| 2948 Heap* heap = GetHeap(); |
| 2881 for (Object* o = this; | 2949 for (Object* o = this; |
| 2882 o != Heap::null_value(); | 2950 o != heap->null_value(); |
| 2883 o = JSObject::cast(o)->GetPrototype()) { | 2951 o = JSObject::cast(o)->GetPrototype()) { |
| 2884 JSObject* curr = JSObject::cast(o); | 2952 JSObject* curr = JSObject::cast(o); |
| 2885 if (!curr->map()->instance_descriptors()->HasEnumCache()) return false; | 2953 if (!curr->map()->instance_descriptors()->HasEnumCache()) return false; |
| 2886 ASSERT(!curr->HasNamedInterceptor()); | 2954 ASSERT(!curr->HasNamedInterceptor()); |
| 2887 ASSERT(!curr->HasIndexedInterceptor()); | 2955 ASSERT(!curr->HasIndexedInterceptor()); |
| 2888 ASSERT(!curr->IsAccessCheckNeeded()); | 2956 ASSERT(!curr->IsAccessCheckNeeded()); |
| 2889 if (curr->NumberOfEnumElements() > 0) return false; | 2957 if (curr->NumberOfEnumElements() > 0) return false; |
| 2890 if (curr != this) { | 2958 if (curr != this) { |
| 2891 FixedArray* curr_fixed_array = | 2959 FixedArray* curr_fixed_array = |
| 2892 FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache()); | 2960 FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2938 return descs->GetCallbacks(i); | 3006 return descs->GetCallbacks(i); |
| 2939 } | 3007 } |
| 2940 } | 3008 } |
| 2941 return NULL; | 3009 return NULL; |
| 2942 } | 3010 } |
| 2943 | 3011 |
| 2944 | 3012 |
| 2945 void JSObject::LocalLookup(String* name, LookupResult* result) { | 3013 void JSObject::LocalLookup(String* name, LookupResult* result) { |
| 2946 ASSERT(name->IsString()); | 3014 ASSERT(name->IsString()); |
| 2947 | 3015 |
| 3016 Heap* heap = GetHeap(); |
| 3017 |
| 2948 if (IsJSGlobalProxy()) { | 3018 if (IsJSGlobalProxy()) { |
| 2949 Object* proto = GetPrototype(); | 3019 Object* proto = GetPrototype(); |
| 2950 if (proto->IsNull()) return result->NotFound(); | 3020 if (proto->IsNull()) return result->NotFound(); |
| 2951 ASSERT(proto->IsJSGlobalObject()); | 3021 ASSERT(proto->IsJSGlobalObject()); |
| 2952 return JSObject::cast(proto)->LocalLookup(name, result); | 3022 return JSObject::cast(proto)->LocalLookup(name, result); |
| 2953 } | 3023 } |
| 2954 | 3024 |
| 2955 // Do not use inline caching if the object is a non-global object | 3025 // Do not use inline caching if the object is a non-global object |
| 2956 // that requires access checks. | 3026 // that requires access checks. |
| 2957 if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) { | 3027 if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) { |
| 2958 result->DisallowCaching(); | 3028 result->DisallowCaching(); |
| 2959 } | 3029 } |
| 2960 | 3030 |
| 2961 // Check __proto__ before interceptor. | 3031 // Check __proto__ before interceptor. |
| 2962 if (name->Equals(Heap::Proto_symbol()) && !IsJSContextExtensionObject()) { | 3032 if (name->Equals(heap->Proto_symbol()) && |
| 3033 !IsJSContextExtensionObject()) { |
| 2963 result->ConstantResult(this); | 3034 result->ConstantResult(this); |
| 2964 return; | 3035 return; |
| 2965 } | 3036 } |
| 2966 | 3037 |
| 2967 // Check for lookup interceptor except when bootstrapping. | 3038 // Check for lookup interceptor except when bootstrapping. |
| 2968 if (HasNamedInterceptor() && !Bootstrapper::IsActive()) { | 3039 if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { |
| 2969 result->InterceptorResult(this); | 3040 result->InterceptorResult(this); |
| 2970 return; | 3041 return; |
| 2971 } | 3042 } |
| 2972 | 3043 |
| 2973 LocalLookupRealNamedProperty(name, result); | 3044 LocalLookupRealNamedProperty(name, result); |
| 2974 } | 3045 } |
| 2975 | 3046 |
| 2976 | 3047 |
| 2977 void JSObject::Lookup(String* name, LookupResult* result) { | 3048 void JSObject::Lookup(String* name, LookupResult* result) { |
| 2978 // Ecma-262 3rd 8.6.2.4 | 3049 // Ecma-262 3rd 8.6.2.4 |
| 3050 Heap* heap = GetHeap(); |
| 2979 for (Object* current = this; | 3051 for (Object* current = this; |
| 2980 current != Heap::null_value(); | 3052 current != heap->null_value(); |
| 2981 current = JSObject::cast(current)->GetPrototype()) { | 3053 current = JSObject::cast(current)->GetPrototype()) { |
| 2982 JSObject::cast(current)->LocalLookup(name, result); | 3054 JSObject::cast(current)->LocalLookup(name, result); |
| 2983 if (result->IsProperty()) return; | 3055 if (result->IsProperty()) return; |
| 2984 } | 3056 } |
| 2985 result->NotFound(); | 3057 result->NotFound(); |
| 2986 } | 3058 } |
| 2987 | 3059 |
| 2988 | 3060 |
| 2989 // Search object and it's prototype chain for callback properties. | 3061 // Search object and it's prototype chain for callback properties. |
| 2990 void JSObject::LookupCallback(String* name, LookupResult* result) { | 3062 void JSObject::LookupCallback(String* name, LookupResult* result) { |
| 3063 Heap* heap = GetHeap(); |
| 2991 for (Object* current = this; | 3064 for (Object* current = this; |
| 2992 current != Heap::null_value(); | 3065 current != heap->null_value(); |
| 2993 current = JSObject::cast(current)->GetPrototype()) { | 3066 current = JSObject::cast(current)->GetPrototype()) { |
| 2994 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); | 3067 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); |
| 2995 if (result->IsProperty() && result->type() == CALLBACKS) return; | 3068 if (result->IsProperty() && result->type() == CALLBACKS) return; |
| 2996 } | 3069 } |
| 2997 result->NotFound(); | 3070 result->NotFound(); |
| 2998 } | 3071 } |
| 2999 | 3072 |
| 3000 | 3073 |
| 3001 MaybeObject* JSObject::DefineGetterSetter(String* name, | 3074 MaybeObject* JSObject::DefineGetterSetter(String* name, |
| 3002 PropertyAttributes attributes) { | 3075 PropertyAttributes attributes) { |
| 3076 Heap* heap = GetHeap(); |
| 3003 // Make sure that the top context does not change when doing callbacks or | 3077 // Make sure that the top context does not change when doing callbacks or |
| 3004 // interceptor calls. | 3078 // interceptor calls. |
| 3005 AssertNoContextChange ncc; | 3079 AssertNoContextChange ncc; |
| 3006 | 3080 |
| 3007 // Try to flatten before operating on the string. | 3081 // Try to flatten before operating on the string. |
| 3008 name->TryFlatten(); | 3082 name->TryFlatten(); |
| 3009 | 3083 |
| 3010 if (!CanSetCallback(name)) { | 3084 if (!CanSetCallback(name)) { |
| 3011 return Heap::undefined_value(); | 3085 return heap->undefined_value(); |
| 3012 } | 3086 } |
| 3013 | 3087 |
| 3014 uint32_t index = 0; | 3088 uint32_t index = 0; |
| 3015 bool is_element = name->AsArrayIndex(&index); | 3089 bool is_element = name->AsArrayIndex(&index); |
| 3016 | 3090 |
| 3017 if (is_element) { | 3091 if (is_element) { |
| 3018 switch (GetElementsKind()) { | 3092 switch (GetElementsKind()) { |
| 3019 case FAST_ELEMENTS: | 3093 case FAST_ELEMENTS: |
| 3020 break; | 3094 break; |
| 3021 case EXTERNAL_PIXEL_ELEMENTS: | 3095 case EXTERNAL_PIXEL_ELEMENTS: |
| 3022 case EXTERNAL_BYTE_ELEMENTS: | 3096 case EXTERNAL_BYTE_ELEMENTS: |
| 3023 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3097 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3024 case EXTERNAL_SHORT_ELEMENTS: | 3098 case EXTERNAL_SHORT_ELEMENTS: |
| 3025 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3099 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3026 case EXTERNAL_INT_ELEMENTS: | 3100 case EXTERNAL_INT_ELEMENTS: |
| 3027 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3101 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3028 case EXTERNAL_FLOAT_ELEMENTS: | 3102 case EXTERNAL_FLOAT_ELEMENTS: |
| 3029 // Ignore getters and setters on pixel and external array | 3103 // Ignore getters and setters on pixel and external array |
| 3030 // elements. | 3104 // elements. |
| 3031 return Heap::undefined_value(); | 3105 return heap->undefined_value(); |
| 3032 case DICTIONARY_ELEMENTS: { | 3106 case DICTIONARY_ELEMENTS: { |
| 3033 // Lookup the index. | 3107 // Lookup the index. |
| 3034 NumberDictionary* dictionary = element_dictionary(); | 3108 NumberDictionary* dictionary = element_dictionary(); |
| 3035 int entry = dictionary->FindEntry(index); | 3109 int entry = dictionary->FindEntry(index); |
| 3036 if (entry != NumberDictionary::kNotFound) { | 3110 if (entry != NumberDictionary::kNotFound) { |
| 3037 Object* result = dictionary->ValueAt(entry); | 3111 Object* result = dictionary->ValueAt(entry); |
| 3038 PropertyDetails details = dictionary->DetailsAt(entry); | 3112 PropertyDetails details = dictionary->DetailsAt(entry); |
| 3039 if (details.IsReadOnly()) return Heap::undefined_value(); | 3113 if (details.IsReadOnly()) return heap->undefined_value(); |
| 3040 if (details.type() == CALLBACKS) { | 3114 if (details.type() == CALLBACKS) { |
| 3041 if (result->IsFixedArray()) { | 3115 if (result->IsFixedArray()) { |
| 3042 return result; | 3116 return result; |
| 3043 } | 3117 } |
| 3044 // Otherwise allow to override it. | 3118 // Otherwise allow to override it. |
| 3045 } | 3119 } |
| 3046 } | 3120 } |
| 3047 break; | 3121 break; |
| 3048 } | 3122 } |
| 3049 default: | 3123 default: |
| 3050 UNREACHABLE(); | 3124 UNREACHABLE(); |
| 3051 break; | 3125 break; |
| 3052 } | 3126 } |
| 3053 } else { | 3127 } else { |
| 3054 // Lookup the name. | 3128 // Lookup the name. |
| 3055 LookupResult result; | 3129 LookupResult result; |
| 3056 LocalLookup(name, &result); | 3130 LocalLookup(name, &result); |
| 3057 if (result.IsProperty()) { | 3131 if (result.IsProperty()) { |
| 3058 if (result.IsReadOnly()) return Heap::undefined_value(); | 3132 if (result.IsReadOnly()) return heap->undefined_value(); |
| 3059 if (result.type() == CALLBACKS) { | 3133 if (result.type() == CALLBACKS) { |
| 3060 Object* obj = result.GetCallbackObject(); | 3134 Object* obj = result.GetCallbackObject(); |
| 3061 // Need to preserve old getters/setters. | 3135 // Need to preserve old getters/setters. |
| 3062 if (obj->IsFixedArray()) { | 3136 if (obj->IsFixedArray()) { |
| 3063 // Use set to update attributes. | 3137 // Use set to update attributes. |
| 3064 return SetPropertyCallback(name, obj, attributes); | 3138 return SetPropertyCallback(name, obj, attributes); |
| 3065 } | 3139 } |
| 3066 } | 3140 } |
| 3067 } | 3141 } |
| 3068 } | 3142 } |
| 3069 | 3143 |
| 3070 // Allocate the fixed array to hold getter and setter. | 3144 // Allocate the fixed array to hold getter and setter. |
| 3071 Object* structure; | 3145 Object* structure; |
| 3072 { MaybeObject* maybe_structure = Heap::AllocateFixedArray(2, TENURED); | 3146 { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED); |
| 3073 if (!maybe_structure->ToObject(&structure)) return maybe_structure; | 3147 if (!maybe_structure->ToObject(&structure)) return maybe_structure; |
| 3074 } | 3148 } |
| 3075 | 3149 |
| 3076 if (is_element) { | 3150 if (is_element) { |
| 3077 return SetElementCallback(index, structure, attributes); | 3151 return SetElementCallback(index, structure, attributes); |
| 3078 } else { | 3152 } else { |
| 3079 return SetPropertyCallback(name, structure, attributes); | 3153 return SetPropertyCallback(name, structure, attributes); |
| 3080 } | 3154 } |
| 3081 } | 3155 } |
| 3082 | 3156 |
| 3083 | 3157 |
| 3084 bool JSObject::CanSetCallback(String* name) { | 3158 bool JSObject::CanSetCallback(String* name) { |
| 3085 ASSERT(!IsAccessCheckNeeded() | 3159 ASSERT(!IsAccessCheckNeeded() |
| 3086 || Top::MayNamedAccess(this, name, v8::ACCESS_SET)); | 3160 || Isolate::Current()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
| 3087 | 3161 |
| 3088 // Check if there is an API defined callback object which prohibits | 3162 // Check if there is an API defined callback object which prohibits |
| 3089 // callback overwriting in this object or it's prototype chain. | 3163 // callback overwriting in this object or it's prototype chain. |
| 3090 // This mechanism is needed for instance in a browser setting, where | 3164 // This mechanism is needed for instance in a browser setting, where |
| 3091 // certain accessors such as window.location should not be allowed | 3165 // certain accessors such as window.location should not be allowed |
| 3092 // to be overwritten because allowing overwriting could potentially | 3166 // to be overwritten because allowing overwriting could potentially |
| 3093 // cause security problems. | 3167 // cause security problems. |
| 3094 LookupResult callback_result; | 3168 LookupResult callback_result; |
| 3095 LookupCallback(name, &callback_result); | 3169 LookupCallback(name, &callback_result); |
| 3096 if (callback_result.IsProperty()) { | 3170 if (callback_result.IsProperty()) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3173 } | 3247 } |
| 3174 } | 3248 } |
| 3175 return result; | 3249 return result; |
| 3176 } | 3250 } |
| 3177 | 3251 |
| 3178 MaybeObject* JSObject::DefineAccessor(String* name, | 3252 MaybeObject* JSObject::DefineAccessor(String* name, |
| 3179 bool is_getter, | 3253 bool is_getter, |
| 3180 Object* fun, | 3254 Object* fun, |
| 3181 PropertyAttributes attributes) { | 3255 PropertyAttributes attributes) { |
| 3182 ASSERT(fun->IsJSFunction() || fun->IsUndefined()); | 3256 ASSERT(fun->IsJSFunction() || fun->IsUndefined()); |
| 3257 Isolate* isolate = GetIsolate(); |
| 3183 // Check access rights if needed. | 3258 // Check access rights if needed. |
| 3184 if (IsAccessCheckNeeded() && | 3259 if (IsAccessCheckNeeded() && |
| 3185 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 3260 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 3186 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 3261 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 3187 return Heap::undefined_value(); | 3262 return isolate->heap()->undefined_value(); |
| 3188 } | 3263 } |
| 3189 | 3264 |
| 3190 if (IsJSGlobalProxy()) { | 3265 if (IsJSGlobalProxy()) { |
| 3191 Object* proto = GetPrototype(); | 3266 Object* proto = GetPrototype(); |
| 3192 if (proto->IsNull()) return this; | 3267 if (proto->IsNull()) return this; |
| 3193 ASSERT(proto->IsJSGlobalObject()); | 3268 ASSERT(proto->IsJSGlobalObject()); |
| 3194 return JSObject::cast(proto)->DefineAccessor(name, is_getter, | 3269 return JSObject::cast(proto)->DefineAccessor(name, is_getter, |
| 3195 fun, attributes); | 3270 fun, attributes); |
| 3196 } | 3271 } |
| 3197 | 3272 |
| 3198 Object* array; | 3273 Object* array; |
| 3199 { MaybeObject* maybe_array = DefineGetterSetter(name, attributes); | 3274 { MaybeObject* maybe_array = DefineGetterSetter(name, attributes); |
| 3200 if (!maybe_array->ToObject(&array)) return maybe_array; | 3275 if (!maybe_array->ToObject(&array)) return maybe_array; |
| 3201 } | 3276 } |
| 3202 if (array->IsUndefined()) return array; | 3277 if (array->IsUndefined()) return array; |
| 3203 FixedArray::cast(array)->set(is_getter ? 0 : 1, fun); | 3278 FixedArray::cast(array)->set(is_getter ? 0 : 1, fun); |
| 3204 return this; | 3279 return this; |
| 3205 } | 3280 } |
| 3206 | 3281 |
| 3207 | 3282 |
| 3208 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { | 3283 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { |
| 3284 Isolate* isolate = GetIsolate(); |
| 3209 String* name = String::cast(info->name()); | 3285 String* name = String::cast(info->name()); |
| 3210 // Check access rights if needed. | 3286 // Check access rights if needed. |
| 3211 if (IsAccessCheckNeeded() && | 3287 if (IsAccessCheckNeeded() && |
| 3212 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 3288 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 3213 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 3289 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 3214 return Heap::undefined_value(); | 3290 return isolate->heap()->undefined_value(); |
| 3215 } | 3291 } |
| 3216 | 3292 |
| 3217 if (IsJSGlobalProxy()) { | 3293 if (IsJSGlobalProxy()) { |
| 3218 Object* proto = GetPrototype(); | 3294 Object* proto = GetPrototype(); |
| 3219 if (proto->IsNull()) return this; | 3295 if (proto->IsNull()) return this; |
| 3220 ASSERT(proto->IsJSGlobalObject()); | 3296 ASSERT(proto->IsJSGlobalObject()); |
| 3221 return JSObject::cast(proto)->DefineAccessor(info); | 3297 return JSObject::cast(proto)->DefineAccessor(info); |
| 3222 } | 3298 } |
| 3223 | 3299 |
| 3224 // Make sure that the top context does not change when doing callbacks or | 3300 // Make sure that the top context does not change when doing callbacks or |
| 3225 // interceptor calls. | 3301 // interceptor calls. |
| 3226 AssertNoContextChange ncc; | 3302 AssertNoContextChange ncc; |
| 3227 | 3303 |
| 3228 // Try to flatten before operating on the string. | 3304 // Try to flatten before operating on the string. |
| 3229 name->TryFlatten(); | 3305 name->TryFlatten(); |
| 3230 | 3306 |
| 3231 if (!CanSetCallback(name)) { | 3307 if (!CanSetCallback(name)) { |
| 3232 return Heap::undefined_value(); | 3308 return isolate->heap()->undefined_value(); |
| 3233 } | 3309 } |
| 3234 | 3310 |
| 3235 uint32_t index = 0; | 3311 uint32_t index = 0; |
| 3236 bool is_element = name->AsArrayIndex(&index); | 3312 bool is_element = name->AsArrayIndex(&index); |
| 3237 | 3313 |
| 3238 if (is_element) { | 3314 if (is_element) { |
| 3239 if (IsJSArray()) return Heap::undefined_value(); | 3315 if (IsJSArray()) return isolate->heap()->undefined_value(); |
| 3240 | 3316 |
| 3241 // Accessors overwrite previous callbacks (cf. with getters/setters). | 3317 // Accessors overwrite previous callbacks (cf. with getters/setters). |
| 3242 switch (GetElementsKind()) { | 3318 switch (GetElementsKind()) { |
| 3243 case FAST_ELEMENTS: | 3319 case FAST_ELEMENTS: |
| 3244 break; | 3320 break; |
| 3245 case EXTERNAL_PIXEL_ELEMENTS: | 3321 case EXTERNAL_PIXEL_ELEMENTS: |
| 3246 case EXTERNAL_BYTE_ELEMENTS: | 3322 case EXTERNAL_BYTE_ELEMENTS: |
| 3247 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3323 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3248 case EXTERNAL_SHORT_ELEMENTS: | 3324 case EXTERNAL_SHORT_ELEMENTS: |
| 3249 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3325 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3250 case EXTERNAL_INT_ELEMENTS: | 3326 case EXTERNAL_INT_ELEMENTS: |
| 3251 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3327 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3252 case EXTERNAL_FLOAT_ELEMENTS: | 3328 case EXTERNAL_FLOAT_ELEMENTS: |
| 3253 // Ignore getters and setters on pixel and external array | 3329 // Ignore getters and setters on pixel and external array |
| 3254 // elements. | 3330 // elements. |
| 3255 return Heap::undefined_value(); | 3331 return isolate->heap()->undefined_value(); |
| 3256 case DICTIONARY_ELEMENTS: | 3332 case DICTIONARY_ELEMENTS: |
| 3257 break; | 3333 break; |
| 3258 default: | 3334 default: |
| 3259 UNREACHABLE(); | 3335 UNREACHABLE(); |
| 3260 break; | 3336 break; |
| 3261 } | 3337 } |
| 3262 | 3338 |
| 3263 Object* ok; | 3339 Object* ok; |
| 3264 { MaybeObject* maybe_ok = | 3340 { MaybeObject* maybe_ok = |
| 3265 SetElementCallback(index, info, info->property_attributes()); | 3341 SetElementCallback(index, info, info->property_attributes()); |
| 3266 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 3342 if (!maybe_ok->ToObject(&ok)) return maybe_ok; |
| 3267 } | 3343 } |
| 3268 } else { | 3344 } else { |
| 3269 // Lookup the name. | 3345 // Lookup the name. |
| 3270 LookupResult result; | 3346 LookupResult result; |
| 3271 LocalLookup(name, &result); | 3347 LocalLookup(name, &result); |
| 3272 // ES5 forbids turning a property into an accessor if it's not | 3348 // ES5 forbids turning a property into an accessor if it's not |
| 3273 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). | 3349 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). |
| 3274 if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) { | 3350 if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) { |
| 3275 return Heap::undefined_value(); | 3351 return isolate->heap()->undefined_value(); |
| 3276 } | 3352 } |
| 3277 Object* ok; | 3353 Object* ok; |
| 3278 { MaybeObject* maybe_ok = | 3354 { MaybeObject* maybe_ok = |
| 3279 SetPropertyCallback(name, info, info->property_attributes()); | 3355 SetPropertyCallback(name, info, info->property_attributes()); |
| 3280 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 3356 if (!maybe_ok->ToObject(&ok)) return maybe_ok; |
| 3281 } | 3357 } |
| 3282 } | 3358 } |
| 3283 | 3359 |
| 3284 return this; | 3360 return this; |
| 3285 } | 3361 } |
| 3286 | 3362 |
| 3287 | 3363 |
| 3288 Object* JSObject::LookupAccessor(String* name, bool is_getter) { | 3364 Object* JSObject::LookupAccessor(String* name, bool is_getter) { |
| 3365 Heap* heap = GetHeap(); |
| 3366 |
| 3289 // Make sure that the top context does not change when doing callbacks or | 3367 // Make sure that the top context does not change when doing callbacks or |
| 3290 // interceptor calls. | 3368 // interceptor calls. |
| 3291 AssertNoContextChange ncc; | 3369 AssertNoContextChange ncc; |
| 3292 | 3370 |
| 3293 // Check access rights if needed. | 3371 // Check access rights if needed. |
| 3294 if (IsAccessCheckNeeded() && | 3372 if (IsAccessCheckNeeded() && |
| 3295 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) { | 3373 !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { |
| 3296 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 3374 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 3297 return Heap::undefined_value(); | 3375 return heap->undefined_value(); |
| 3298 } | 3376 } |
| 3299 | 3377 |
| 3300 // Make the lookup and include prototypes. | 3378 // Make the lookup and include prototypes. |
| 3301 int accessor_index = is_getter ? kGetterIndex : kSetterIndex; | 3379 int accessor_index = is_getter ? kGetterIndex : kSetterIndex; |
| 3302 uint32_t index = 0; | 3380 uint32_t index = 0; |
| 3303 if (name->AsArrayIndex(&index)) { | 3381 if (name->AsArrayIndex(&index)) { |
| 3304 for (Object* obj = this; | 3382 for (Object* obj = this; |
| 3305 obj != Heap::null_value(); | 3383 obj != heap->null_value(); |
| 3306 obj = JSObject::cast(obj)->GetPrototype()) { | 3384 obj = JSObject::cast(obj)->GetPrototype()) { |
| 3307 JSObject* js_object = JSObject::cast(obj); | 3385 JSObject* js_object = JSObject::cast(obj); |
| 3308 if (js_object->HasDictionaryElements()) { | 3386 if (js_object->HasDictionaryElements()) { |
| 3309 NumberDictionary* dictionary = js_object->element_dictionary(); | 3387 NumberDictionary* dictionary = js_object->element_dictionary(); |
| 3310 int entry = dictionary->FindEntry(index); | 3388 int entry = dictionary->FindEntry(index); |
| 3311 if (entry != NumberDictionary::kNotFound) { | 3389 if (entry != NumberDictionary::kNotFound) { |
| 3312 Object* element = dictionary->ValueAt(entry); | 3390 Object* element = dictionary->ValueAt(entry); |
| 3313 PropertyDetails details = dictionary->DetailsAt(entry); | 3391 PropertyDetails details = dictionary->DetailsAt(entry); |
| 3314 if (details.type() == CALLBACKS) { | 3392 if (details.type() == CALLBACKS) { |
| 3315 if (element->IsFixedArray()) { | 3393 if (element->IsFixedArray()) { |
| 3316 return FixedArray::cast(element)->get(accessor_index); | 3394 return FixedArray::cast(element)->get(accessor_index); |
| 3317 } | 3395 } |
| 3318 } | 3396 } |
| 3319 } | 3397 } |
| 3320 } | 3398 } |
| 3321 } | 3399 } |
| 3322 } else { | 3400 } else { |
| 3323 for (Object* obj = this; | 3401 for (Object* obj = this; |
| 3324 obj != Heap::null_value(); | 3402 obj != heap->null_value(); |
| 3325 obj = JSObject::cast(obj)->GetPrototype()) { | 3403 obj = JSObject::cast(obj)->GetPrototype()) { |
| 3326 LookupResult result; | 3404 LookupResult result; |
| 3327 JSObject::cast(obj)->LocalLookup(name, &result); | 3405 JSObject::cast(obj)->LocalLookup(name, &result); |
| 3328 if (result.IsProperty()) { | 3406 if (result.IsProperty()) { |
| 3329 if (result.IsReadOnly()) return Heap::undefined_value(); | 3407 if (result.IsReadOnly()) return heap->undefined_value(); |
| 3330 if (result.type() == CALLBACKS) { | 3408 if (result.type() == CALLBACKS) { |
| 3331 Object* obj = result.GetCallbackObject(); | 3409 Object* obj = result.GetCallbackObject(); |
| 3332 if (obj->IsFixedArray()) { | 3410 if (obj->IsFixedArray()) { |
| 3333 return FixedArray::cast(obj)->get(accessor_index); | 3411 return FixedArray::cast(obj)->get(accessor_index); |
| 3334 } | 3412 } |
| 3335 } | 3413 } |
| 3336 } | 3414 } |
| 3337 } | 3415 } |
| 3338 } | 3416 } |
| 3339 return Heap::undefined_value(); | 3417 return heap->undefined_value(); |
| 3340 } | 3418 } |
| 3341 | 3419 |
| 3342 | 3420 |
| 3343 Object* JSObject::SlowReverseLookup(Object* value) { | 3421 Object* JSObject::SlowReverseLookup(Object* value) { |
| 3422 Heap* heap = GetHeap(); |
| 3344 if (HasFastProperties()) { | 3423 if (HasFastProperties()) { |
| 3345 DescriptorArray* descs = map()->instance_descriptors(); | 3424 DescriptorArray* descs = map()->instance_descriptors(); |
| 3346 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 3425 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
| 3347 if (descs->GetType(i) == FIELD) { | 3426 if (descs->GetType(i) == FIELD) { |
| 3348 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { | 3427 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { |
| 3349 return descs->GetKey(i); | 3428 return descs->GetKey(i); |
| 3350 } | 3429 } |
| 3351 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { | 3430 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { |
| 3352 if (descs->GetConstantFunction(i) == value) { | 3431 if (descs->GetConstantFunction(i) == value) { |
| 3353 return descs->GetKey(i); | 3432 return descs->GetKey(i); |
| 3354 } | 3433 } |
| 3355 } | 3434 } |
| 3356 } | 3435 } |
| 3357 return Heap::undefined_value(); | 3436 return heap->undefined_value(); |
| 3358 } else { | 3437 } else { |
| 3359 return property_dictionary()->SlowReverseLookup(value); | 3438 return property_dictionary()->SlowReverseLookup(value); |
| 3360 } | 3439 } |
| 3361 } | 3440 } |
| 3362 | 3441 |
| 3363 | 3442 |
| 3364 MaybeObject* Map::CopyDropDescriptors() { | 3443 MaybeObject* Map::CopyDropDescriptors() { |
| 3444 Heap* heap = GetHeap(); |
| 3365 Object* result; | 3445 Object* result; |
| 3366 { MaybeObject* maybe_result = | 3446 { MaybeObject* maybe_result = |
| 3367 Heap::AllocateMap(instance_type(), instance_size()); | 3447 heap->AllocateMap(instance_type(), instance_size()); |
| 3368 if (!maybe_result->ToObject(&result)) return maybe_result; | 3448 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3369 } | 3449 } |
| 3370 Map::cast(result)->set_prototype(prototype()); | 3450 Map::cast(result)->set_prototype(prototype()); |
| 3371 Map::cast(result)->set_constructor(constructor()); | 3451 Map::cast(result)->set_constructor(constructor()); |
| 3372 // Don't copy descriptors, so map transitions always remain a forest. | 3452 // Don't copy descriptors, so map transitions always remain a forest. |
| 3373 // If we retained the same descriptors we would have two maps | 3453 // If we retained the same descriptors we would have two maps |
| 3374 // pointing to the same transition which is bad because the garbage | 3454 // pointing to the same transition which is bad because the garbage |
| 3375 // collector relies on being able to reverse pointers from transitions | 3455 // collector relies on being able to reverse pointers from transitions |
| 3376 // to maps. If properties need to be retained use CopyDropTransitions. | 3456 // to maps. If properties need to be retained use CopyDropTransitions. |
| 3377 Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array()); | 3457 Map::cast(result)->set_instance_descriptors( |
| 3458 heap->empty_descriptor_array()); |
| 3378 // Please note instance_type and instance_size are set when allocated. | 3459 // Please note instance_type and instance_size are set when allocated. |
| 3379 Map::cast(result)->set_inobject_properties(inobject_properties()); | 3460 Map::cast(result)->set_inobject_properties(inobject_properties()); |
| 3380 Map::cast(result)->set_unused_property_fields(unused_property_fields()); | 3461 Map::cast(result)->set_unused_property_fields(unused_property_fields()); |
| 3381 | 3462 |
| 3382 // If the map has pre-allocated properties always start out with a descriptor | 3463 // If the map has pre-allocated properties always start out with a descriptor |
| 3383 // array describing these properties. | 3464 // array describing these properties. |
| 3384 if (pre_allocated_property_fields() > 0) { | 3465 if (pre_allocated_property_fields() > 0) { |
| 3385 ASSERT(constructor()->IsJSFunction()); | 3466 ASSERT(constructor()->IsJSFunction()); |
| 3386 JSFunction* ctor = JSFunction::cast(constructor()); | 3467 JSFunction* ctor = JSFunction::cast(constructor()); |
| 3387 Object* descriptors; | 3468 Object* descriptors; |
| 3388 { MaybeObject* maybe_descriptors = | 3469 { MaybeObject* maybe_descriptors = |
| 3389 ctor->initial_map()->instance_descriptors()->RemoveTransitions(); | 3470 ctor->initial_map()->instance_descriptors()->RemoveTransitions(); |
| 3390 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; | 3471 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; |
| 3391 } | 3472 } |
| 3392 Map::cast(result)->set_instance_descriptors( | 3473 Map::cast(result)->set_instance_descriptors( |
| 3393 DescriptorArray::cast(descriptors)); | 3474 DescriptorArray::cast(descriptors)); |
| 3394 Map::cast(result)->set_pre_allocated_property_fields( | 3475 Map::cast(result)->set_pre_allocated_property_fields( |
| 3395 pre_allocated_property_fields()); | 3476 pre_allocated_property_fields()); |
| 3396 } | 3477 } |
| 3397 Map::cast(result)->set_bit_field(bit_field()); | 3478 Map::cast(result)->set_bit_field(bit_field()); |
| 3398 Map::cast(result)->set_bit_field2(bit_field2()); | 3479 Map::cast(result)->set_bit_field2(bit_field2()); |
| 3399 Map::cast(result)->set_is_shared(false); | 3480 Map::cast(result)->set_is_shared(false); |
| 3400 Map::cast(result)->ClearCodeCache(); | 3481 Map::cast(result)->ClearCodeCache(heap); |
| 3401 return result; | 3482 return result; |
| 3402 } | 3483 } |
| 3403 | 3484 |
| 3404 | 3485 |
| 3405 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, | 3486 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, |
| 3406 NormalizedMapSharingMode sharing) { | 3487 NormalizedMapSharingMode sharing) { |
| 3407 int new_instance_size = instance_size(); | 3488 int new_instance_size = instance_size(); |
| 3408 if (mode == CLEAR_INOBJECT_PROPERTIES) { | 3489 if (mode == CLEAR_INOBJECT_PROPERTIES) { |
| 3409 new_instance_size -= inobject_properties() * kPointerSize; | 3490 new_instance_size -= inobject_properties() * kPointerSize; |
| 3410 } | 3491 } |
| 3411 | 3492 |
| 3412 Object* result; | 3493 Object* result; |
| 3413 { MaybeObject* maybe_result = | 3494 { MaybeObject* maybe_result = |
| 3414 Heap::AllocateMap(instance_type(), new_instance_size); | 3495 GetHeap()->AllocateMap(instance_type(), new_instance_size); |
| 3415 if (!maybe_result->ToObject(&result)) return maybe_result; | 3496 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3416 } | 3497 } |
| 3417 | 3498 |
| 3418 if (mode != CLEAR_INOBJECT_PROPERTIES) { | 3499 if (mode != CLEAR_INOBJECT_PROPERTIES) { |
| 3419 Map::cast(result)->set_inobject_properties(inobject_properties()); | 3500 Map::cast(result)->set_inobject_properties(inobject_properties()); |
| 3420 } | 3501 } |
| 3421 | 3502 |
| 3422 Map::cast(result)->set_prototype(prototype()); | 3503 Map::cast(result)->set_prototype(prototype()); |
| 3423 Map::cast(result)->set_constructor(constructor()); | 3504 Map::cast(result)->set_constructor(constructor()); |
| 3424 | 3505 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3449 } | 3530 } |
| 3450 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); | 3531 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); |
| 3451 return new_map; | 3532 return new_map; |
| 3452 } | 3533 } |
| 3453 | 3534 |
| 3454 | 3535 |
| 3455 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { | 3536 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { |
| 3456 // Allocate the code cache if not present. | 3537 // Allocate the code cache if not present. |
| 3457 if (code_cache()->IsFixedArray()) { | 3538 if (code_cache()->IsFixedArray()) { |
| 3458 Object* result; | 3539 Object* result; |
| 3459 { MaybeObject* maybe_result = Heap::AllocateCodeCache(); | 3540 { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache(); |
| 3460 if (!maybe_result->ToObject(&result)) return maybe_result; | 3541 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3461 } | 3542 } |
| 3462 set_code_cache(result); | 3543 set_code_cache(result); |
| 3463 } | 3544 } |
| 3464 | 3545 |
| 3465 // Update the code cache. | 3546 // Update the code cache. |
| 3466 return CodeCache::cast(code_cache())->Update(name, code); | 3547 return CodeCache::cast(code_cache())->Update(name, code); |
| 3467 } | 3548 } |
| 3468 | 3549 |
| 3469 | 3550 |
| 3470 Object* Map::FindInCodeCache(String* name, Code::Flags flags) { | 3551 Object* Map::FindInCodeCache(String* name, Code::Flags flags) { |
| 3471 // Do a lookup if a code cache exists. | 3552 // Do a lookup if a code cache exists. |
| 3472 if (!code_cache()->IsFixedArray()) { | 3553 if (!code_cache()->IsFixedArray()) { |
| 3473 return CodeCache::cast(code_cache())->Lookup(name, flags); | 3554 return CodeCache::cast(code_cache())->Lookup(name, flags); |
| 3474 } else { | 3555 } else { |
| 3475 return Heap::undefined_value(); | 3556 return GetHeap()->undefined_value(); |
| 3476 } | 3557 } |
| 3477 } | 3558 } |
| 3478 | 3559 |
| 3479 | 3560 |
| 3480 int Map::IndexInCodeCache(Object* name, Code* code) { | 3561 int Map::IndexInCodeCache(Object* name, Code* code) { |
| 3481 // Get the internal index if a code cache exists. | 3562 // Get the internal index if a code cache exists. |
| 3482 if (!code_cache()->IsFixedArray()) { | 3563 if (!code_cache()->IsFixedArray()) { |
| 3483 return CodeCache::cast(code_cache())->GetIndex(name, code); | 3564 return CodeCache::cast(code_cache())->GetIndex(name, code); |
| 3484 } | 3565 } |
| 3485 return -1; | 3566 return -1; |
| 3486 } | 3567 } |
| 3487 | 3568 |
| 3488 | 3569 |
| 3489 void Map::RemoveFromCodeCache(String* name, Code* code, int index) { | 3570 void Map::RemoveFromCodeCache(String* name, Code* code, int index) { |
| 3490 // No GC is supposed to happen between a call to IndexInCodeCache and | 3571 // No GC is supposed to happen between a call to IndexInCodeCache and |
| 3491 // RemoveFromCodeCache so the code cache must be there. | 3572 // RemoveFromCodeCache so the code cache must be there. |
| 3492 ASSERT(!code_cache()->IsFixedArray()); | 3573 ASSERT(!code_cache()->IsFixedArray()); |
| 3493 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); | 3574 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); |
| 3494 } | 3575 } |
| 3495 | 3576 |
| 3496 | 3577 |
| 3497 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { | 3578 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { |
| 3498 Map* current = this; | 3579 Map* current = this; |
| 3499 while (current != Heap::meta_map()) { | 3580 Map* meta_map = heap()->meta_map(); |
| 3581 while (current != meta_map) { |
| 3500 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( | 3582 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( |
| 3501 *RawField(current, Map::kInstanceDescriptorsOffset)); | 3583 *RawField(current, Map::kInstanceDescriptorsOffset)); |
| 3502 if (d == Heap::empty_descriptor_array()) { | 3584 if (d == heap()->empty_descriptor_array()) { |
| 3503 Map* prev = current->map(); | 3585 Map* prev = current->map(); |
| 3504 current->set_map(Heap::meta_map()); | 3586 current->set_map(meta_map); |
| 3505 callback(current, data); | 3587 callback(current, data); |
| 3506 current = prev; | 3588 current = prev; |
| 3507 continue; | 3589 continue; |
| 3508 } | 3590 } |
| 3509 | 3591 |
| 3510 FixedArray* contents = reinterpret_cast<FixedArray*>( | 3592 FixedArray* contents = reinterpret_cast<FixedArray*>( |
| 3511 d->get(DescriptorArray::kContentArrayIndex)); | 3593 d->get(DescriptorArray::kContentArrayIndex)); |
| 3512 Object** map_or_index_field = RawField(contents, HeapObject::kMapOffset); | 3594 Object** map_or_index_field = RawField(contents, HeapObject::kMapOffset); |
| 3513 Object* map_or_index = *map_or_index_field; | 3595 Object* map_or_index = *map_or_index_field; |
| 3514 bool map_done = true; | 3596 bool map_done = true; |
| 3515 for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0; | 3597 for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0; |
| 3516 i < contents->length(); | 3598 i < contents->length(); |
| 3517 i += 2) { | 3599 i += 2) { |
| 3518 PropertyDetails details(Smi::cast(contents->get(i + 1))); | 3600 PropertyDetails details(Smi::cast(contents->get(i + 1))); |
| 3519 if (details.IsTransition()) { | 3601 if (details.IsTransition()) { |
| 3520 Map* next = reinterpret_cast<Map*>(contents->get(i)); | 3602 Map* next = reinterpret_cast<Map*>(contents->get(i)); |
| 3521 next->set_map(current); | 3603 next->set_map(current); |
| 3522 *map_or_index_field = Smi::FromInt(i + 2); | 3604 *map_or_index_field = Smi::FromInt(i + 2); |
| 3523 current = next; | 3605 current = next; |
| 3524 map_done = false; | 3606 map_done = false; |
| 3525 break; | 3607 break; |
| 3526 } | 3608 } |
| 3527 } | 3609 } |
| 3528 if (!map_done) continue; | 3610 if (!map_done) continue; |
| 3529 *map_or_index_field = Heap::fixed_array_map(); | 3611 *map_or_index_field = heap()->fixed_array_map(); |
| 3530 Map* prev = current->map(); | 3612 Map* prev = current->map(); |
| 3531 current->set_map(Heap::meta_map()); | 3613 current->set_map(meta_map); |
| 3532 callback(current, data); | 3614 callback(current, data); |
| 3533 current = prev; | 3615 current = prev; |
| 3534 } | 3616 } |
| 3535 } | 3617 } |
| 3536 | 3618 |
| 3537 | 3619 |
| 3538 MaybeObject* CodeCache::Update(String* name, Code* code) { | 3620 MaybeObject* CodeCache::Update(String* name, Code* code) { |
| 3539 ASSERT(code->ic_state() == MONOMORPHIC); | 3621 ASSERT(code->ic_state() == MONOMORPHIC); |
| 3540 | 3622 |
| 3541 // The number of monomorphic stubs for normal load/store/call IC's can grow to | 3623 // The number of monomorphic stubs for normal load/store/call IC's can grow to |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3634 Object* CodeCache::Lookup(String* name, Code::Flags flags) { | 3716 Object* CodeCache::Lookup(String* name, Code::Flags flags) { |
| 3635 if (Code::ExtractTypeFromFlags(flags) == NORMAL) { | 3717 if (Code::ExtractTypeFromFlags(flags) == NORMAL) { |
| 3636 return LookupNormalTypeCache(name, flags); | 3718 return LookupNormalTypeCache(name, flags); |
| 3637 } else { | 3719 } else { |
| 3638 return LookupDefaultCache(name, flags); | 3720 return LookupDefaultCache(name, flags); |
| 3639 } | 3721 } |
| 3640 } | 3722 } |
| 3641 | 3723 |
| 3642 | 3724 |
| 3643 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) { | 3725 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) { |
| 3726 Heap* heap = GetHeap(); |
| 3644 FixedArray* cache = default_cache(); | 3727 FixedArray* cache = default_cache(); |
| 3645 int length = cache->length(); | 3728 int length = cache->length(); |
| 3646 for (int i = 0; i < length; i += kCodeCacheEntrySize) { | 3729 for (int i = 0; i < length; i += kCodeCacheEntrySize) { |
| 3647 Object* key = cache->get(i + kCodeCacheEntryNameOffset); | 3730 Object* key = cache->get(i + kCodeCacheEntryNameOffset); |
| 3648 // Skip deleted elements. | 3731 // Skip deleted elements. |
| 3649 if (key->IsNull()) continue; | 3732 if (key->IsNull()) continue; |
| 3650 if (key->IsUndefined()) return key; | 3733 if (key->IsUndefined()) return key; |
| 3651 if (name->Equals(String::cast(key))) { | 3734 if (name->Equals(String::cast(key))) { |
| 3652 Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset)); | 3735 Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset)); |
| 3653 if (code->flags() == flags) { | 3736 if (code->flags() == flags) { |
| 3654 return code; | 3737 return code; |
| 3655 } | 3738 } |
| 3656 } | 3739 } |
| 3657 } | 3740 } |
| 3658 return Heap::undefined_value(); | 3741 return heap->undefined_value(); |
| 3659 } | 3742 } |
| 3660 | 3743 |
| 3661 | 3744 |
| 3662 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) { | 3745 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) { |
| 3663 if (!normal_type_cache()->IsUndefined()) { | 3746 if (!normal_type_cache()->IsUndefined()) { |
| 3664 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); | 3747 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); |
| 3665 return cache->Lookup(name, flags); | 3748 return cache->Lookup(name, flags); |
| 3666 } else { | 3749 } else { |
| 3667 return Heap::undefined_value(); | 3750 return GetHeap()->undefined_value(); |
| 3668 } | 3751 } |
| 3669 } | 3752 } |
| 3670 | 3753 |
| 3671 | 3754 |
| 3672 int CodeCache::GetIndex(Object* name, Code* code) { | 3755 int CodeCache::GetIndex(Object* name, Code* code) { |
| 3673 if (code->type() == NORMAL) { | 3756 if (code->type() == NORMAL) { |
| 3674 if (normal_type_cache()->IsUndefined()) return -1; | 3757 if (normal_type_cache()->IsUndefined()) return -1; |
| 3675 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); | 3758 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); |
| 3676 return cache->GetIndex(String::cast(name), code->flags()); | 3759 return cache->GetIndex(String::cast(name), code->flags()); |
| 3677 } | 3760 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3739 uint32_t HashForObject(Object* obj) { | 3822 uint32_t HashForObject(Object* obj) { |
| 3740 FixedArray* pair = FixedArray::cast(obj); | 3823 FixedArray* pair = FixedArray::cast(obj); |
| 3741 String* name = String::cast(pair->get(0)); | 3824 String* name = String::cast(pair->get(0)); |
| 3742 Code* code = Code::cast(pair->get(1)); | 3825 Code* code = Code::cast(pair->get(1)); |
| 3743 return NameFlagsHashHelper(name, code->flags()); | 3826 return NameFlagsHashHelper(name, code->flags()); |
| 3744 } | 3827 } |
| 3745 | 3828 |
| 3746 MUST_USE_RESULT MaybeObject* AsObject() { | 3829 MUST_USE_RESULT MaybeObject* AsObject() { |
| 3747 ASSERT(code_ != NULL); | 3830 ASSERT(code_ != NULL); |
| 3748 Object* obj; | 3831 Object* obj; |
| 3749 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(2); | 3832 { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2); |
| 3750 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3833 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3751 } | 3834 } |
| 3752 FixedArray* pair = FixedArray::cast(obj); | 3835 FixedArray* pair = FixedArray::cast(obj); |
| 3753 pair->set(0, name_); | 3836 pair->set(0, name_); |
| 3754 pair->set(1, code_); | 3837 pair->set(1, code_); |
| 3755 return pair; | 3838 return pair; |
| 3756 } | 3839 } |
| 3757 | 3840 |
| 3758 private: | 3841 private: |
| 3759 String* name_; | 3842 String* name_; |
| 3760 Code::Flags flags_; | 3843 Code::Flags flags_; |
| 3761 Code* code_; | 3844 Code* code_; |
| 3762 }; | 3845 }; |
| 3763 | 3846 |
| 3764 | 3847 |
| 3765 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) { | 3848 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) { |
| 3766 CodeCacheHashTableKey key(name, flags); | 3849 CodeCacheHashTableKey key(name, flags); |
| 3767 int entry = FindEntry(&key); | 3850 int entry = FindEntry(&key); |
| 3768 if (entry == kNotFound) return Heap::undefined_value(); | 3851 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 3769 return get(EntryToIndex(entry) + 1); | 3852 return get(EntryToIndex(entry) + 1); |
| 3770 } | 3853 } |
| 3771 | 3854 |
| 3772 | 3855 |
| 3773 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) { | 3856 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) { |
| 3774 CodeCacheHashTableKey key(name, code); | 3857 CodeCacheHashTableKey key(name, code); |
| 3775 Object* obj; | 3858 Object* obj; |
| 3776 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 3859 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 3777 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3860 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3778 } | 3861 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3795 | 3878 |
| 3796 int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) { | 3879 int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) { |
| 3797 CodeCacheHashTableKey key(name, flags); | 3880 CodeCacheHashTableKey key(name, flags); |
| 3798 int entry = FindEntry(&key); | 3881 int entry = FindEntry(&key); |
| 3799 return (entry == kNotFound) ? -1 : entry; | 3882 return (entry == kNotFound) ? -1 : entry; |
| 3800 } | 3883 } |
| 3801 | 3884 |
| 3802 | 3885 |
| 3803 void CodeCacheHashTable::RemoveByIndex(int index) { | 3886 void CodeCacheHashTable::RemoveByIndex(int index) { |
| 3804 ASSERT(index >= 0); | 3887 ASSERT(index >= 0); |
| 3805 set(EntryToIndex(index), Heap::null_value()); | 3888 Heap* heap = GetHeap(); |
| 3806 set(EntryToIndex(index) + 1, Heap::null_value()); | 3889 set(EntryToIndex(index), heap->null_value()); |
| 3890 set(EntryToIndex(index) + 1, heap->null_value()); |
| 3807 ElementRemoved(); | 3891 ElementRemoved(); |
| 3808 } | 3892 } |
| 3809 | 3893 |
| 3810 | 3894 |
| 3811 static bool HasKey(FixedArray* array, Object* key) { | 3895 static bool HasKey(FixedArray* array, Object* key) { |
| 3812 int len0 = array->length(); | 3896 int len0 = array->length(); |
| 3813 for (int i = 0; i < len0; i++) { | 3897 for (int i = 0; i < len0; i++) { |
| 3814 Object* element = array->get(i); | 3898 Object* element = array->get(i); |
| 3815 if (element->IsSmi() && key->IsSmi() && (element == key)) return true; | 3899 if (element->IsSmi() && key->IsSmi() && (element == key)) return true; |
| 3816 if (element->IsString() && | 3900 if (element->IsString() && |
| 3817 key->IsString() && String::cast(element)->Equals(String::cast(key))) { | 3901 key->IsString() && String::cast(element)->Equals(String::cast(key))) { |
| 3818 return true; | 3902 return true; |
| 3819 } | 3903 } |
| 3820 } | 3904 } |
| 3821 return false; | 3905 return false; |
| 3822 } | 3906 } |
| 3823 | 3907 |
| 3824 | 3908 |
| 3825 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { | 3909 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { |
| 3910 Heap* heap = GetHeap(); |
| 3826 ASSERT(!array->HasExternalArrayElements()); | 3911 ASSERT(!array->HasExternalArrayElements()); |
| 3827 switch (array->GetElementsKind()) { | 3912 switch (array->GetElementsKind()) { |
| 3828 case JSObject::FAST_ELEMENTS: | 3913 case JSObject::FAST_ELEMENTS: |
| 3829 return UnionOfKeys(FixedArray::cast(array->elements())); | 3914 return UnionOfKeys(FixedArray::cast(array->elements())); |
| 3830 case JSObject::DICTIONARY_ELEMENTS: { | 3915 case JSObject::DICTIONARY_ELEMENTS: { |
| 3831 NumberDictionary* dict = array->element_dictionary(); | 3916 NumberDictionary* dict = array->element_dictionary(); |
| 3832 int size = dict->NumberOfElements(); | 3917 int size = dict->NumberOfElements(); |
| 3833 | 3918 |
| 3834 // Allocate a temporary fixed array. | 3919 // Allocate a temporary fixed array. |
| 3835 Object* object; | 3920 Object* object; |
| 3836 { MaybeObject* maybe_object = Heap::AllocateFixedArray(size); | 3921 { MaybeObject* maybe_object = heap->AllocateFixedArray(size); |
| 3837 if (!maybe_object->ToObject(&object)) return maybe_object; | 3922 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 3838 } | 3923 } |
| 3839 FixedArray* key_array = FixedArray::cast(object); | 3924 FixedArray* key_array = FixedArray::cast(object); |
| 3840 | 3925 |
| 3841 int capacity = dict->Capacity(); | 3926 int capacity = dict->Capacity(); |
| 3842 int pos = 0; | 3927 int pos = 0; |
| 3843 // Copy the elements from the JSArray to the temporary fixed array. | 3928 // Copy the elements from the JSArray to the temporary fixed array. |
| 3844 for (int i = 0; i < capacity; i++) { | 3929 for (int i = 0; i < capacity; i++) { |
| 3845 if (dict->IsKey(dict->KeyAt(i))) { | 3930 if (dict->IsKey(dict->KeyAt(i))) { |
| 3846 key_array->set(pos++, dict->ValueAt(i)); | 3931 key_array->set(pos++, dict->ValueAt(i)); |
| 3847 } | 3932 } |
| 3848 } | 3933 } |
| 3849 // Compute the union of this and the temporary fixed array. | 3934 // Compute the union of this and the temporary fixed array. |
| 3850 return UnionOfKeys(key_array); | 3935 return UnionOfKeys(key_array); |
| 3851 } | 3936 } |
| 3852 default: | 3937 default: |
| 3853 UNREACHABLE(); | 3938 UNREACHABLE(); |
| 3854 } | 3939 } |
| 3855 UNREACHABLE(); | 3940 UNREACHABLE(); |
| 3856 return Heap::null_value(); // Failure case needs to "return" a value. | 3941 return heap->null_value(); // Failure case needs to "return" a value. |
| 3857 } | 3942 } |
| 3858 | 3943 |
| 3859 | 3944 |
| 3860 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { | 3945 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { |
| 3946 Heap* heap = GetHeap(); |
| 3861 int len0 = length(); | 3947 int len0 = length(); |
| 3862 #ifdef DEBUG | 3948 #ifdef DEBUG |
| 3863 if (FLAG_enable_slow_asserts) { | 3949 if (FLAG_enable_slow_asserts) { |
| 3864 for (int i = 0; i < len0; i++) { | 3950 for (int i = 0; i < len0; i++) { |
| 3865 ASSERT(get(i)->IsString() || get(i)->IsNumber()); | 3951 ASSERT(get(i)->IsString() || get(i)->IsNumber()); |
| 3866 } | 3952 } |
| 3867 } | 3953 } |
| 3868 #endif | 3954 #endif |
| 3869 int len1 = other->length(); | 3955 int len1 = other->length(); |
| 3870 // Optimize if 'other' is empty. | 3956 // Optimize if 'other' is empty. |
| 3871 // We cannot optimize if 'this' is empty, as other may have holes | 3957 // We cannot optimize if 'this' is empty, as other may have holes |
| 3872 // or non keys. | 3958 // or non keys. |
| 3873 if (len1 == 0) return this; | 3959 if (len1 == 0) return this; |
| 3874 | 3960 |
| 3875 // Compute how many elements are not in this. | 3961 // Compute how many elements are not in this. |
| 3876 int extra = 0; | 3962 int extra = 0; |
| 3877 for (int y = 0; y < len1; y++) { | 3963 for (int y = 0; y < len1; y++) { |
| 3878 Object* value = other->get(y); | 3964 Object* value = other->get(y); |
| 3879 if (!value->IsTheHole() && !HasKey(this, value)) extra++; | 3965 if (!value->IsTheHole() && !HasKey(this, value)) extra++; |
| 3880 } | 3966 } |
| 3881 | 3967 |
| 3882 if (extra == 0) return this; | 3968 if (extra == 0) return this; |
| 3883 | 3969 |
| 3884 // Allocate the result | 3970 // Allocate the result |
| 3885 Object* obj; | 3971 Object* obj; |
| 3886 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(len0 + extra); | 3972 { MaybeObject* maybe_obj = heap->AllocateFixedArray(len0 + extra); |
| 3887 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3973 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3888 } | 3974 } |
| 3889 // Fill in the content | 3975 // Fill in the content |
| 3890 AssertNoAllocation no_gc; | 3976 AssertNoAllocation no_gc; |
| 3891 FixedArray* result = FixedArray::cast(obj); | 3977 FixedArray* result = FixedArray::cast(obj); |
| 3892 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 3978 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 3893 for (int i = 0; i < len0; i++) { | 3979 for (int i = 0; i < len0; i++) { |
| 3894 Object* e = get(i); | 3980 Object* e = get(i); |
| 3895 ASSERT(e->IsString() || e->IsNumber()); | 3981 ASSERT(e->IsString() || e->IsNumber()); |
| 3896 result->set(i, e, mode); | 3982 result->set(i, e, mode); |
| 3897 } | 3983 } |
| 3898 // Fill in the extra keys. | 3984 // Fill in the extra keys. |
| 3899 int index = 0; | 3985 int index = 0; |
| 3900 for (int y = 0; y < len1; y++) { | 3986 for (int y = 0; y < len1; y++) { |
| 3901 Object* value = other->get(y); | 3987 Object* value = other->get(y); |
| 3902 if (!value->IsTheHole() && !HasKey(this, value)) { | 3988 if (!value->IsTheHole() && !HasKey(this, value)) { |
| 3903 Object* e = other->get(y); | 3989 Object* e = other->get(y); |
| 3904 ASSERT(e->IsString() || e->IsNumber()); | 3990 ASSERT(e->IsString() || e->IsNumber()); |
| 3905 result->set(len0 + index, e, mode); | 3991 result->set(len0 + index, e, mode); |
| 3906 index++; | 3992 index++; |
| 3907 } | 3993 } |
| 3908 } | 3994 } |
| 3909 ASSERT(extra == index); | 3995 ASSERT(extra == index); |
| 3910 return result; | 3996 return result; |
| 3911 } | 3997 } |
| 3912 | 3998 |
| 3913 | 3999 |
| 3914 MaybeObject* FixedArray::CopySize(int new_length) { | 4000 MaybeObject* FixedArray::CopySize(int new_length) { |
| 3915 if (new_length == 0) return Heap::empty_fixed_array(); | 4001 Heap* heap = GetHeap(); |
| 4002 if (new_length == 0) return heap->empty_fixed_array(); |
| 3916 Object* obj; | 4003 Object* obj; |
| 3917 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(new_length); | 4004 { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length); |
| 3918 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 4005 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3919 } | 4006 } |
| 3920 FixedArray* result = FixedArray::cast(obj); | 4007 FixedArray* result = FixedArray::cast(obj); |
| 3921 // Copy the content | 4008 // Copy the content |
| 3922 AssertNoAllocation no_gc; | 4009 AssertNoAllocation no_gc; |
| 3923 int len = length(); | 4010 int len = length(); |
| 3924 if (new_length < len) len = new_length; | 4011 if (new_length < len) len = new_length; |
| 3925 result->set_map(map()); | 4012 result->set_map(map()); |
| 3926 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 4013 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 3927 for (int i = 0; i < len; i++) { | 4014 for (int i = 0; i < len; i++) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3945 if (length() != other->length()) return false; | 4032 if (length() != other->length()) return false; |
| 3946 for (int i = 0 ; i < length(); ++i) { | 4033 for (int i = 0 ; i < length(); ++i) { |
| 3947 if (get(i) != other->get(i)) return false; | 4034 if (get(i) != other->get(i)) return false; |
| 3948 } | 4035 } |
| 3949 return true; | 4036 return true; |
| 3950 } | 4037 } |
| 3951 #endif | 4038 #endif |
| 3952 | 4039 |
| 3953 | 4040 |
| 3954 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { | 4041 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { |
| 4042 Heap* heap = Isolate::Current()->heap(); |
| 3955 if (number_of_descriptors == 0) { | 4043 if (number_of_descriptors == 0) { |
| 3956 return Heap::empty_descriptor_array(); | 4044 return heap->empty_descriptor_array(); |
| 3957 } | 4045 } |
| 3958 // Allocate the array of keys. | 4046 // Allocate the array of keys. |
| 3959 Object* array; | 4047 Object* array; |
| 3960 { MaybeObject* maybe_array = | 4048 { MaybeObject* maybe_array = |
| 3961 Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors)); | 4049 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors)); |
| 3962 if (!maybe_array->ToObject(&array)) return maybe_array; | 4050 if (!maybe_array->ToObject(&array)) return maybe_array; |
| 3963 } | 4051 } |
| 3964 // Do not use DescriptorArray::cast on incomplete object. | 4052 // Do not use DescriptorArray::cast on incomplete object. |
| 3965 FixedArray* result = FixedArray::cast(array); | 4053 FixedArray* result = FixedArray::cast(array); |
| 3966 | 4054 |
| 3967 // Allocate the content array and set it in the descriptor array. | 4055 // Allocate the content array and set it in the descriptor array. |
| 3968 { MaybeObject* maybe_array = | 4056 { MaybeObject* maybe_array = |
| 3969 Heap::AllocateFixedArray(number_of_descriptors << 1); | 4057 heap->AllocateFixedArray(number_of_descriptors << 1); |
| 3970 if (!maybe_array->ToObject(&array)) return maybe_array; | 4058 if (!maybe_array->ToObject(&array)) return maybe_array; |
| 3971 } | 4059 } |
| 3972 result->set(kContentArrayIndex, array); | 4060 result->set(kContentArrayIndex, array); |
| 3973 result->set(kEnumerationIndexIndex, | 4061 result->set(kEnumerationIndexIndex, |
| 3974 Smi::FromInt(PropertyDetails::kInitialIndex)); | 4062 Smi::FromInt(PropertyDetails::kInitialIndex)); |
| 3975 return result; | 4063 return result; |
| 3976 } | 4064 } |
| 3977 | 4065 |
| 3978 | 4066 |
| 3979 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 4067 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4228 return number; | 4316 return number; |
| 4229 } | 4317 } |
| 4230 } | 4318 } |
| 4231 return kNotFound; | 4319 return kNotFound; |
| 4232 } | 4320 } |
| 4233 | 4321 |
| 4234 | 4322 |
| 4235 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count, | 4323 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count, |
| 4236 PretenureFlag pretenure) { | 4324 PretenureFlag pretenure) { |
| 4237 ASSERT(deopt_entry_count > 0); | 4325 ASSERT(deopt_entry_count > 0); |
| 4238 return Heap::AllocateFixedArray(LengthFor(deopt_entry_count), | 4326 return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count), |
| 4239 pretenure); | 4327 pretenure); |
| 4240 } | 4328 } |
| 4241 | 4329 |
| 4242 | 4330 |
| 4243 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points, | 4331 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points, |
| 4244 PretenureFlag pretenure) { | 4332 PretenureFlag pretenure) { |
| 4245 if (number_of_deopt_points == 0) return Heap::empty_fixed_array(); | 4333 if (number_of_deopt_points == 0) return HEAP->empty_fixed_array(); |
| 4246 return Heap::AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points), | 4334 return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points), |
| 4247 pretenure); | 4335 pretenure); |
| 4248 } | 4336 } |
| 4249 | 4337 |
| 4250 | 4338 |
| 4251 #ifdef DEBUG | 4339 #ifdef DEBUG |
| 4252 bool DescriptorArray::IsEqualTo(DescriptorArray* other) { | 4340 bool DescriptorArray::IsEqualTo(DescriptorArray* other) { |
| 4253 if (IsEmpty()) return other->IsEmpty(); | 4341 if (IsEmpty()) return other->IsEmpty(); |
| 4254 if (other->IsEmpty()) return false; | 4342 if (other->IsEmpty()) return false; |
| 4255 if (length() != other->length()) return false; | 4343 if (length() != other->length()) return false; |
| 4256 for (int i = 0; i < length(); ++i) { | 4344 for (int i = 0; i < length(); ++i) { |
| 4257 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; | 4345 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; |
| 4258 } | 4346 } |
| 4259 return GetContentArray()->IsEqualTo(other->GetContentArray()); | 4347 return GetContentArray()->IsEqualTo(other->GetContentArray()); |
| 4260 } | 4348 } |
| 4261 #endif | 4349 #endif |
| 4262 | 4350 |
| 4263 | 4351 |
| 4264 static StaticResource<StringInputBuffer> string_input_buffer; | |
| 4265 | |
| 4266 | |
| 4267 bool String::LooksValid() { | 4352 bool String::LooksValid() { |
| 4268 if (!Heap::Contains(this)) return false; | 4353 if (!Isolate::Current()->heap()->Contains(this)) return false; |
| 4269 return true; | 4354 return true; |
| 4270 } | 4355 } |
| 4271 | 4356 |
| 4272 | 4357 |
| 4273 int String::Utf8Length() { | 4358 int String::Utf8Length() { |
| 4274 if (IsAsciiRepresentation()) return length(); | 4359 if (IsAsciiRepresentation()) return length(); |
| 4275 // Attempt to flatten before accessing the string. It probably | 4360 // Attempt to flatten before accessing the string. It probably |
| 4276 // doesn't make Utf8Length faster, but it is very likely that | 4361 // doesn't make Utf8Length faster, but it is very likely that |
| 4277 // the string will be accessed later (for example by WriteUtf8) | 4362 // the string will be accessed later (for example by WriteUtf8) |
| 4278 // so it's still a good idea. | 4363 // so it's still a good idea. |
| 4364 Heap* heap = GetHeap(); |
| 4279 TryFlatten(); | 4365 TryFlatten(); |
| 4280 Access<StringInputBuffer> buffer(&string_input_buffer); | 4366 Access<StringInputBuffer> buffer( |
| 4367 heap->isolate()->objects_string_input_buffer()); |
| 4281 buffer->Reset(0, this); | 4368 buffer->Reset(0, this); |
| 4282 int result = 0; | 4369 int result = 0; |
| 4283 while (buffer->has_more()) | 4370 while (buffer->has_more()) |
| 4284 result += unibrow::Utf8::Length(buffer->GetNext()); | 4371 result += unibrow::Utf8::Length(buffer->GetNext()); |
| 4285 return result; | 4372 return result; |
| 4286 } | 4373 } |
| 4287 | 4374 |
| 4288 | 4375 |
| 4289 Vector<const char> String::ToAsciiVector() { | 4376 Vector<const char> String::ToAsciiVector() { |
| 4290 ASSERT(IsAsciiRepresentation()); | 4377 ASSERT(IsAsciiRepresentation()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4340 | 4427 |
| 4341 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, | 4428 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, |
| 4342 RobustnessFlag robust_flag, | 4429 RobustnessFlag robust_flag, |
| 4343 int offset, | 4430 int offset, |
| 4344 int length, | 4431 int length, |
| 4345 int* length_return) { | 4432 int* length_return) { |
| 4346 ASSERT(NativeAllocationChecker::allocation_allowed()); | 4433 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 4347 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 4434 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 4348 return SmartPointer<char>(NULL); | 4435 return SmartPointer<char>(NULL); |
| 4349 } | 4436 } |
| 4437 Heap* heap = GetHeap(); |
| 4350 | 4438 |
| 4351 // Negative length means the to the end of the string. | 4439 // Negative length means the to the end of the string. |
| 4352 if (length < 0) length = kMaxInt - offset; | 4440 if (length < 0) length = kMaxInt - offset; |
| 4353 | 4441 |
| 4354 // Compute the size of the UTF-8 string. Start at the specified offset. | 4442 // Compute the size of the UTF-8 string. Start at the specified offset. |
| 4355 Access<StringInputBuffer> buffer(&string_input_buffer); | 4443 Access<StringInputBuffer> buffer( |
| 4444 heap->isolate()->objects_string_input_buffer()); |
| 4356 buffer->Reset(offset, this); | 4445 buffer->Reset(offset, this); |
| 4357 int character_position = offset; | 4446 int character_position = offset; |
| 4358 int utf8_bytes = 0; | 4447 int utf8_bytes = 0; |
| 4359 while (buffer->has_more()) { | 4448 while (buffer->has_more()) { |
| 4360 uint16_t character = buffer->GetNext(); | 4449 uint16_t character = buffer->GetNext(); |
| 4361 if (character_position < offset + length) { | 4450 if (character_position < offset + length) { |
| 4362 utf8_bytes += unibrow::Utf8::Length(character); | 4451 utf8_bytes += unibrow::Utf8::Length(character); |
| 4363 } | 4452 } |
| 4364 character_position++; | 4453 character_position++; |
| 4365 } | 4454 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4415 UNREACHABLE(); | 4504 UNREACHABLE(); |
| 4416 return NULL; | 4505 return NULL; |
| 4417 } | 4506 } |
| 4418 UNREACHABLE(); | 4507 UNREACHABLE(); |
| 4419 return NULL; | 4508 return NULL; |
| 4420 } | 4509 } |
| 4421 | 4510 |
| 4422 | 4511 |
| 4423 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { | 4512 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { |
| 4424 ASSERT(NativeAllocationChecker::allocation_allowed()); | 4513 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 4425 | |
| 4426 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 4514 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 4427 return SmartPointer<uc16>(); | 4515 return SmartPointer<uc16>(); |
| 4428 } | 4516 } |
| 4517 Heap* heap = GetHeap(); |
| 4429 | 4518 |
| 4430 Access<StringInputBuffer> buffer(&string_input_buffer); | 4519 Access<StringInputBuffer> buffer( |
| 4520 heap->isolate()->objects_string_input_buffer()); |
| 4431 buffer->Reset(this); | 4521 buffer->Reset(this); |
| 4432 | 4522 |
| 4433 uc16* result = NewArray<uc16>(length() + 1); | 4523 uc16* result = NewArray<uc16>(length() + 1); |
| 4434 | 4524 |
| 4435 int i = 0; | 4525 int i = 0; |
| 4436 while (buffer->has_more()) { | 4526 while (buffer->has_more()) { |
| 4437 uint16_t character = buffer->GetNext(); | 4527 uint16_t character = buffer->GetNext(); |
| 4438 result[i++] = character; | 4528 result[i++] = character; |
| 4439 } | 4529 } |
| 4440 result[i] = 0; | 4530 result[i] = 0; |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4703 } | 4793 } |
| 4704 default: | 4794 default: |
| 4705 break; | 4795 break; |
| 4706 } | 4796 } |
| 4707 | 4797 |
| 4708 UNREACHABLE(); | 4798 UNREACHABLE(); |
| 4709 return 0; | 4799 return 0; |
| 4710 } | 4800 } |
| 4711 | 4801 |
| 4712 | 4802 |
| 4713 Relocatable* Relocatable::top_ = NULL; | |
| 4714 | |
| 4715 | |
| 4716 void Relocatable::PostGarbageCollectionProcessing() { | 4803 void Relocatable::PostGarbageCollectionProcessing() { |
| 4717 Relocatable* current = top_; | 4804 Isolate* isolate = Isolate::Current(); |
| 4805 Relocatable* current = isolate->relocatable_top(); |
| 4718 while (current != NULL) { | 4806 while (current != NULL) { |
| 4719 current->PostGarbageCollection(); | 4807 current->PostGarbageCollection(); |
| 4720 current = current->prev_; | 4808 current = current->prev_; |
| 4721 } | 4809 } |
| 4722 } | 4810 } |
| 4723 | 4811 |
| 4724 | 4812 |
| 4725 // Reserve space for statics needing saving and restoring. | 4813 // Reserve space for statics needing saving and restoring. |
| 4726 int Relocatable::ArchiveSpacePerThread() { | 4814 int Relocatable::ArchiveSpacePerThread() { |
| 4727 return sizeof(top_); | 4815 return sizeof(Isolate::Current()->relocatable_top()); |
| 4728 } | 4816 } |
| 4729 | 4817 |
| 4730 | 4818 |
| 4731 // Archive statics that are thread local. | 4819 // Archive statics that are thread local. |
| 4732 char* Relocatable::ArchiveState(char* to) { | 4820 char* Relocatable::ArchiveState(char* to) { |
| 4733 *reinterpret_cast<Relocatable**>(to) = top_; | 4821 Isolate* isolate = Isolate::Current(); |
| 4734 top_ = NULL; | 4822 *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top(); |
| 4823 isolate->set_relocatable_top(NULL); |
| 4735 return to + ArchiveSpacePerThread(); | 4824 return to + ArchiveSpacePerThread(); |
| 4736 } | 4825 } |
| 4737 | 4826 |
| 4738 | 4827 |
| 4739 // Restore statics that are thread local. | 4828 // Restore statics that are thread local. |
| 4740 char* Relocatable::RestoreState(char* from) { | 4829 char* Relocatable::RestoreState(char* from) { |
| 4741 top_ = *reinterpret_cast<Relocatable**>(from); | 4830 Isolate* isolate = Isolate::Current(); |
| 4831 isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from)); |
| 4742 return from + ArchiveSpacePerThread(); | 4832 return from + ArchiveSpacePerThread(); |
| 4743 } | 4833 } |
| 4744 | 4834 |
| 4745 | 4835 |
| 4746 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) { | 4836 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) { |
| 4747 Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage); | 4837 Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage); |
| 4748 Iterate(v, top); | 4838 Iterate(v, top); |
| 4749 return thread_storage + ArchiveSpacePerThread(); | 4839 return thread_storage + ArchiveSpacePerThread(); |
| 4750 } | 4840 } |
| 4751 | 4841 |
| 4752 | 4842 |
| 4753 void Relocatable::Iterate(ObjectVisitor* v) { | 4843 void Relocatable::Iterate(ObjectVisitor* v) { |
| 4754 Iterate(v, top_); | 4844 Isolate* isolate = Isolate::Current(); |
| 4845 Iterate(v, isolate->relocatable_top()); |
| 4755 } | 4846 } |
| 4756 | 4847 |
| 4757 | 4848 |
| 4758 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) { | 4849 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) { |
| 4759 Relocatable* current = top; | 4850 Relocatable* current = top; |
| 4760 while (current != NULL) { | 4851 while (current != NULL) { |
| 4761 current->IterateInstance(v); | 4852 current->IterateInstance(v); |
| 4762 current = current->prev_; | 4853 current = current->prev_; |
| 4763 } | 4854 } |
| 4764 } | 4855 } |
| 4765 | 4856 |
| 4766 | 4857 |
| 4767 FlatStringReader::FlatStringReader(Handle<String> str) | 4858 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str) |
| 4768 : str_(str.location()), | 4859 : Relocatable(isolate), |
| 4860 str_(str.location()), |
| 4769 length_(str->length()) { | 4861 length_(str->length()) { |
| 4770 PostGarbageCollection(); | 4862 PostGarbageCollection(); |
| 4771 } | 4863 } |
| 4772 | 4864 |
| 4773 | 4865 |
| 4774 FlatStringReader::FlatStringReader(Vector<const char> input) | 4866 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input) |
| 4775 : str_(0), | 4867 : Relocatable(isolate), |
| 4868 str_(0), |
| 4776 is_ascii_(true), | 4869 is_ascii_(true), |
| 4777 length_(input.length()), | 4870 length_(input.length()), |
| 4778 start_(input.start()) { } | 4871 start_(input.start()) { } |
| 4779 | 4872 |
| 4780 | 4873 |
| 4781 void FlatStringReader::PostGarbageCollection() { | 4874 void FlatStringReader::PostGarbageCollection() { |
| 4782 if (str_ == NULL) return; | 4875 if (str_ == NULL) return; |
| 4783 Handle<String> str(str_); | 4876 Handle<String> str(str_); |
| 4784 ASSERT(str->IsFlat()); | 4877 ASSERT(str->IsFlat()); |
| 4785 is_ascii_ = str->IsAsciiRepresentation(); | 4878 is_ascii_ = str->IsAsciiRepresentation(); |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5095 // Compare the remaining characters that didn't fit into a block. | 5188 // Compare the remaining characters that didn't fit into a block. |
| 5096 for (; i < length; i++) { | 5189 for (; i < length; i++) { |
| 5097 if (a[i] != b[i]) { | 5190 if (a[i] != b[i]) { |
| 5098 return false; | 5191 return false; |
| 5099 } | 5192 } |
| 5100 } | 5193 } |
| 5101 return true; | 5194 return true; |
| 5102 } | 5195 } |
| 5103 | 5196 |
| 5104 | 5197 |
| 5105 static StringInputBuffer string_compare_buffer_b; | |
| 5106 | |
| 5107 | |
| 5108 template <typename IteratorA> | 5198 template <typename IteratorA> |
| 5109 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { | 5199 static inline bool CompareStringContentsPartial(Isolate* isolate, |
| 5200 IteratorA* ia, |
| 5201 String* b) { |
| 5110 if (b->IsFlat()) { | 5202 if (b->IsFlat()) { |
| 5111 if (b->IsAsciiRepresentation()) { | 5203 if (b->IsAsciiRepresentation()) { |
| 5112 VectorIterator<char> ib(b->ToAsciiVector()); | 5204 VectorIterator<char> ib(b->ToAsciiVector()); |
| 5113 return CompareStringContents(ia, &ib); | 5205 return CompareStringContents(ia, &ib); |
| 5114 } else { | 5206 } else { |
| 5115 VectorIterator<uc16> ib(b->ToUC16Vector()); | 5207 VectorIterator<uc16> ib(b->ToUC16Vector()); |
| 5116 return CompareStringContents(ia, &ib); | 5208 return CompareStringContents(ia, &ib); |
| 5117 } | 5209 } |
| 5118 } else { | 5210 } else { |
| 5119 string_compare_buffer_b.Reset(0, b); | 5211 isolate->objects_string_compare_buffer_b()->Reset(0, b); |
| 5120 return CompareStringContents(ia, &string_compare_buffer_b); | 5212 return CompareStringContents(ia, |
| 5213 isolate->objects_string_compare_buffer_b()); |
| 5121 } | 5214 } |
| 5122 } | 5215 } |
| 5123 | 5216 |
| 5124 | 5217 |
| 5125 static StringInputBuffer string_compare_buffer_a; | 5218 bool String::SlowEquals(String* other) { |
| 5219 Heap* heap = GetHeap(); |
| 5126 | 5220 |
| 5127 | |
| 5128 bool String::SlowEquals(String* other) { | |
| 5129 // Fast check: negative check with lengths. | 5221 // Fast check: negative check with lengths. |
| 5130 int len = length(); | 5222 int len = length(); |
| 5131 if (len != other->length()) return false; | 5223 if (len != other->length()) return false; |
| 5132 if (len == 0) return true; | 5224 if (len == 0) return true; |
| 5133 | 5225 |
| 5134 // Fast check: if hash code is computed for both strings | 5226 // Fast check: if hash code is computed for both strings |
| 5135 // a fast negative check can be performed. | 5227 // a fast negative check can be performed. |
| 5136 if (HasHashCode() && other->HasHashCode()) { | 5228 if (HasHashCode() && other->HasHashCode()) { |
| 5137 if (Hash() != other->Hash()) return false; | 5229 if (Hash() != other->Hash()) return false; |
| 5138 } | 5230 } |
| 5139 | 5231 |
| 5140 // We know the strings are both non-empty. Compare the first chars | 5232 // We know the strings are both non-empty. Compare the first chars |
| 5141 // before we try to flatten the strings. | 5233 // before we try to flatten the strings. |
| 5142 if (this->Get(0) != other->Get(0)) return false; | 5234 if (this->Get(0) != other->Get(0)) return false; |
| 5143 | 5235 |
| 5144 String* lhs = this->TryFlattenGetString(); | 5236 String* lhs = this->TryFlattenGetString(); |
| 5145 String* rhs = other->TryFlattenGetString(); | 5237 String* rhs = other->TryFlattenGetString(); |
| 5146 | 5238 |
| 5147 if (StringShape(lhs).IsSequentialAscii() && | 5239 if (StringShape(lhs).IsSequentialAscii() && |
| 5148 StringShape(rhs).IsSequentialAscii()) { | 5240 StringShape(rhs).IsSequentialAscii()) { |
| 5149 const char* str1 = SeqAsciiString::cast(lhs)->GetChars(); | 5241 const char* str1 = SeqAsciiString::cast(lhs)->GetChars(); |
| 5150 const char* str2 = SeqAsciiString::cast(rhs)->GetChars(); | 5242 const char* str2 = SeqAsciiString::cast(rhs)->GetChars(); |
| 5151 return CompareRawStringContents(Vector<const char>(str1, len), | 5243 return CompareRawStringContents(Vector<const char>(str1, len), |
| 5152 Vector<const char>(str2, len)); | 5244 Vector<const char>(str2, len)); |
| 5153 } | 5245 } |
| 5154 | 5246 |
| 5247 Isolate* isolate = heap->isolate(); |
| 5155 if (lhs->IsFlat()) { | 5248 if (lhs->IsFlat()) { |
| 5156 if (lhs->IsAsciiRepresentation()) { | 5249 if (lhs->IsAsciiRepresentation()) { |
| 5157 Vector<const char> vec1 = lhs->ToAsciiVector(); | 5250 Vector<const char> vec1 = lhs->ToAsciiVector(); |
| 5158 if (rhs->IsFlat()) { | 5251 if (rhs->IsFlat()) { |
| 5159 if (rhs->IsAsciiRepresentation()) { | 5252 if (rhs->IsAsciiRepresentation()) { |
| 5160 Vector<const char> vec2 = rhs->ToAsciiVector(); | 5253 Vector<const char> vec2 = rhs->ToAsciiVector(); |
| 5161 return CompareRawStringContents(vec1, vec2); | 5254 return CompareRawStringContents(vec1, vec2); |
| 5162 } else { | 5255 } else { |
| 5163 VectorIterator<char> buf1(vec1); | 5256 VectorIterator<char> buf1(vec1); |
| 5164 VectorIterator<uc16> ib(rhs->ToUC16Vector()); | 5257 VectorIterator<uc16> ib(rhs->ToUC16Vector()); |
| 5165 return CompareStringContents(&buf1, &ib); | 5258 return CompareStringContents(&buf1, &ib); |
| 5166 } | 5259 } |
| 5167 } else { | 5260 } else { |
| 5168 VectorIterator<char> buf1(vec1); | 5261 VectorIterator<char> buf1(vec1); |
| 5169 string_compare_buffer_b.Reset(0, rhs); | 5262 isolate->objects_string_compare_buffer_b()->Reset(0, rhs); |
| 5170 return CompareStringContents(&buf1, &string_compare_buffer_b); | 5263 return CompareStringContents(&buf1, |
| 5264 isolate->objects_string_compare_buffer_b()); |
| 5171 } | 5265 } |
| 5172 } else { | 5266 } else { |
| 5173 Vector<const uc16> vec1 = lhs->ToUC16Vector(); | 5267 Vector<const uc16> vec1 = lhs->ToUC16Vector(); |
| 5174 if (rhs->IsFlat()) { | 5268 if (rhs->IsFlat()) { |
| 5175 if (rhs->IsAsciiRepresentation()) { | 5269 if (rhs->IsAsciiRepresentation()) { |
| 5176 VectorIterator<uc16> buf1(vec1); | 5270 VectorIterator<uc16> buf1(vec1); |
| 5177 VectorIterator<char> ib(rhs->ToAsciiVector()); | 5271 VectorIterator<char> ib(rhs->ToAsciiVector()); |
| 5178 return CompareStringContents(&buf1, &ib); | 5272 return CompareStringContents(&buf1, &ib); |
| 5179 } else { | 5273 } else { |
| 5180 Vector<const uc16> vec2(rhs->ToUC16Vector()); | 5274 Vector<const uc16> vec2(rhs->ToUC16Vector()); |
| 5181 return CompareRawStringContents(vec1, vec2); | 5275 return CompareRawStringContents(vec1, vec2); |
| 5182 } | 5276 } |
| 5183 } else { | 5277 } else { |
| 5184 VectorIterator<uc16> buf1(vec1); | 5278 VectorIterator<uc16> buf1(vec1); |
| 5185 string_compare_buffer_b.Reset(0, rhs); | 5279 isolate->objects_string_compare_buffer_b()->Reset(0, rhs); |
| 5186 return CompareStringContents(&buf1, &string_compare_buffer_b); | 5280 return CompareStringContents(&buf1, |
| 5281 isolate->objects_string_compare_buffer_b()); |
| 5187 } | 5282 } |
| 5188 } | 5283 } |
| 5189 } else { | 5284 } else { |
| 5190 string_compare_buffer_a.Reset(0, lhs); | 5285 isolate->objects_string_compare_buffer_a()->Reset(0, lhs); |
| 5191 return CompareStringContentsPartial(&string_compare_buffer_a, rhs); | 5286 return CompareStringContentsPartial(isolate, |
| 5287 isolate->objects_string_compare_buffer_a(), rhs); |
| 5192 } | 5288 } |
| 5193 } | 5289 } |
| 5194 | 5290 |
| 5195 | 5291 |
| 5196 bool String::MarkAsUndetectable() { | 5292 bool String::MarkAsUndetectable() { |
| 5197 if (StringShape(this).IsSymbol()) return false; | 5293 if (StringShape(this).IsSymbol()) return false; |
| 5198 | 5294 |
| 5199 Map* map = this->map(); | 5295 Map* map = this->map(); |
| 5200 if (map == Heap::string_map()) { | 5296 Heap* heap = map->GetHeap(); |
| 5201 this->set_map(Heap::undetectable_string_map()); | 5297 if (map == heap->string_map()) { |
| 5298 this->set_map(heap->undetectable_string_map()); |
| 5202 return true; | 5299 return true; |
| 5203 } else if (map == Heap::ascii_string_map()) { | 5300 } else if (map == heap->ascii_string_map()) { |
| 5204 this->set_map(Heap::undetectable_ascii_string_map()); | 5301 this->set_map(heap->undetectable_ascii_string_map()); |
| 5205 return true; | 5302 return true; |
| 5206 } | 5303 } |
| 5207 // Rest cannot be marked as undetectable | 5304 // Rest cannot be marked as undetectable |
| 5208 return false; | 5305 return false; |
| 5209 } | 5306 } |
| 5210 | 5307 |
| 5211 | 5308 |
| 5212 bool String::IsEqualTo(Vector<const char> str) { | 5309 bool String::IsEqualTo(Vector<const char> str) { |
| 5310 Isolate* isolate = GetIsolate(); |
| 5213 int slen = length(); | 5311 int slen = length(); |
| 5214 Access<ScannerConstants::Utf8Decoder> | 5312 Access<ScannerConstants::Utf8Decoder> |
| 5215 decoder(ScannerConstants::utf8_decoder()); | 5313 decoder(isolate->scanner_constants()->utf8_decoder()); |
| 5216 decoder->Reset(str.start(), str.length()); | 5314 decoder->Reset(str.start(), str.length()); |
| 5217 int i; | 5315 int i; |
| 5218 for (i = 0; i < slen && decoder->has_more(); i++) { | 5316 for (i = 0; i < slen && decoder->has_more(); i++) { |
| 5219 uc32 r = decoder->GetNext(); | 5317 uc32 r = decoder->GetNext(); |
| 5220 if (Get(i) != r) return false; | 5318 if (Get(i) != r) return false; |
| 5221 } | 5319 } |
| 5222 return i == slen && !decoder->has_more(); | 5320 return i == slen && !decoder->has_more(); |
| 5223 } | 5321 } |
| 5224 | 5322 |
| 5225 | 5323 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5367 // index. | 5465 // index. |
| 5368 while (buffer->has_more()) { | 5466 while (buffer->has_more()) { |
| 5369 hasher.AddCharacterNoIndex(buffer->GetNext()); | 5467 hasher.AddCharacterNoIndex(buffer->GetNext()); |
| 5370 } | 5468 } |
| 5371 | 5469 |
| 5372 return hasher.GetHashField(); | 5470 return hasher.GetHashField(); |
| 5373 } | 5471 } |
| 5374 | 5472 |
| 5375 | 5473 |
| 5376 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) { | 5474 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) { |
| 5475 Heap* heap = GetHeap(); |
| 5377 if (start == 0 && end == length()) return this; | 5476 if (start == 0 && end == length()) return this; |
| 5378 MaybeObject* result = Heap::AllocateSubString(this, start, end, pretenure); | 5477 MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure); |
| 5379 return result; | 5478 return result; |
| 5380 } | 5479 } |
| 5381 | 5480 |
| 5382 | 5481 |
| 5383 void String::PrintOn(FILE* file) { | 5482 void String::PrintOn(FILE* file) { |
| 5384 int length = this->length(); | 5483 int length = this->length(); |
| 5385 for (int i = 0; i < length; i++) { | 5484 for (int i = 0; i < length; i++) { |
| 5386 fprintf(file, "%c", Get(i)); | 5485 fprintf(file, "%c", Get(i)); |
| 5387 } | 5486 } |
| 5388 } | 5487 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 5408 source_prototype == target_prototype); | 5507 source_prototype == target_prototype); |
| 5409 #endif | 5508 #endif |
| 5410 // Point target back to source. set_prototype() will not let us set | 5509 // Point target back to source. set_prototype() will not let us set |
| 5411 // the prototype to a map, as we do here. | 5510 // the prototype to a map, as we do here. |
| 5412 *RawField(target, kPrototypeOffset) = this; | 5511 *RawField(target, kPrototypeOffset) = this; |
| 5413 } | 5512 } |
| 5414 } | 5513 } |
| 5415 } | 5514 } |
| 5416 | 5515 |
| 5417 | 5516 |
| 5418 void Map::ClearNonLiveTransitions(Object* real_prototype) { | 5517 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) { |
| 5419 // Live DescriptorArray objects will be marked, so we must use | 5518 // Live DescriptorArray objects will be marked, so we must use |
| 5420 // low-level accessors to get and modify their data. | 5519 // low-level accessors to get and modify their data. |
| 5421 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( | 5520 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( |
| 5422 *RawField(this, Map::kInstanceDescriptorsOffset)); | 5521 *RawField(this, Map::kInstanceDescriptorsOffset)); |
| 5423 if (d == Heap::raw_unchecked_empty_descriptor_array()) return; | 5522 if (d == heap->raw_unchecked_empty_descriptor_array()) return; |
| 5424 Smi* NullDescriptorDetails = | 5523 Smi* NullDescriptorDetails = |
| 5425 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi(); | 5524 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi(); |
| 5426 FixedArray* contents = reinterpret_cast<FixedArray*>( | 5525 FixedArray* contents = reinterpret_cast<FixedArray*>( |
| 5427 d->get(DescriptorArray::kContentArrayIndex)); | 5526 d->get(DescriptorArray::kContentArrayIndex)); |
| 5428 ASSERT(contents->length() >= 2); | 5527 ASSERT(contents->length() >= 2); |
| 5429 for (int i = 0; i < contents->length(); i += 2) { | 5528 for (int i = 0; i < contents->length(); i += 2) { |
| 5430 // If the pair (value, details) is a map transition, | 5529 // If the pair (value, details) is a map transition, |
| 5431 // check if the target is live. If not, null the descriptor. | 5530 // check if the target is live. If not, null the descriptor. |
| 5432 // Also drop the back pointer for that map transition, so that this | 5531 // Also drop the back pointer for that map transition, so that this |
| 5433 // map is not reached again by following a back pointer from a | 5532 // map is not reached again by following a back pointer from a |
| 5434 // non-live object. | 5533 // non-live object. |
| 5435 PropertyDetails details(Smi::cast(contents->get(i + 1))); | 5534 PropertyDetails details(Smi::cast(contents->get(i + 1))); |
| 5436 if (details.type() == MAP_TRANSITION || | 5535 if (details.type() == MAP_TRANSITION || |
| 5437 details.type() == CONSTANT_TRANSITION) { | 5536 details.type() == CONSTANT_TRANSITION) { |
| 5438 Map* target = reinterpret_cast<Map*>(contents->get(i)); | 5537 Map* target = reinterpret_cast<Map*>(contents->get(i)); |
| 5439 ASSERT(target->IsHeapObject()); | 5538 ASSERT(target->IsHeapObject()); |
| 5440 MarkBit map_mark = Marking::MarkBitFrom(target); | 5539 MarkBit map_mark = heap->marking()->MarkBitFrom(target); |
| 5441 if (!map_mark.Get()) { | 5540 if (!map_mark.Get()) { |
| 5442 ASSERT(target->IsMap()); | 5541 ASSERT(target->IsMap()); |
| 5443 contents->set_unchecked(i + 1, NullDescriptorDetails); | 5542 contents->set_unchecked(i + 1, NullDescriptorDetails); |
| 5444 contents->set_null_unchecked(i); | 5543 contents->set_null_unchecked(heap, i); |
| 5445 ASSERT(target->prototype() == this || | 5544 ASSERT(target->prototype() == this || |
| 5446 target->prototype() == real_prototype); | 5545 target->prototype() == real_prototype); |
| 5447 // Getter prototype() is read-only, set_prototype() has side effects. | 5546 // Getter prototype() is read-only, set_prototype() has side effects. |
| 5448 *RawField(target, Map::kPrototypeOffset) = real_prototype; | 5547 *RawField(target, Map::kPrototypeOffset) = real_prototype; |
| 5449 } | 5548 } |
| 5450 } | 5549 } |
| 5451 } | 5550 } |
| 5452 } | 5551 } |
| 5453 | 5552 |
| 5454 | 5553 |
| 5455 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { | 5554 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { |
| 5456 // Iterate over all fields in the body but take care in dealing with | 5555 // Iterate over all fields in the body but take care in dealing with |
| 5457 // the code entry. | 5556 // the code entry. |
| 5458 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 5557 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
| 5459 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 5558 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
| 5460 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 5559 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
| 5461 } | 5560 } |
| 5462 | 5561 |
| 5463 | 5562 |
| 5464 void JSFunction::MarkForLazyRecompilation() { | 5563 void JSFunction::MarkForLazyRecompilation() { |
| 5465 ASSERT(is_compiled() && !IsOptimized()); | 5564 ASSERT(is_compiled() && !IsOptimized()); |
| 5466 ASSERT(shared()->allows_lazy_compilation() || | 5565 ASSERT(shared()->allows_lazy_compilation() || |
| 5467 code()->optimizable()); | 5566 code()->optimizable()); |
| 5468 ReplaceCode(Builtins::builtin(Builtins::LazyRecompile)); | 5567 Builtins* builtins = GetIsolate()->builtins(); |
| 5568 ReplaceCode(builtins->builtin(Builtins::LazyRecompile)); |
| 5469 } | 5569 } |
| 5470 | 5570 |
| 5471 | 5571 |
| 5472 uint32_t JSFunction::SourceHash() { | 5572 uint32_t JSFunction::SourceHash() { |
| 5473 uint32_t hash = 0; | 5573 uint32_t hash = 0; |
| 5474 Object* script = shared()->script(); | 5574 Object* script = shared()->script(); |
| 5475 if (!script->IsUndefined()) { | 5575 if (!script->IsUndefined()) { |
| 5476 Object* source = Script::cast(script)->source(); | 5576 Object* source = Script::cast(script)->source(); |
| 5477 if (source->IsUndefined()) hash = String::cast(source)->Hash(); | 5577 if (source->IsUndefined()) hash = String::cast(source)->Hash(); |
| 5478 } | 5578 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5491 Code* code = shared_info->code(); | 5591 Code* code = shared_info->code(); |
| 5492 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | 5592 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
| 5493 // If we never ran this (unlikely) then lets try to optimize it. | 5593 // If we never ran this (unlikely) then lets try to optimize it. |
| 5494 if (code->kind() != Code::FUNCTION) return true; | 5594 if (code->kind() != Code::FUNCTION) return true; |
| 5495 return code->optimizable(); | 5595 return code->optimizable(); |
| 5496 } | 5596 } |
| 5497 | 5597 |
| 5498 | 5598 |
| 5499 Object* JSFunction::SetInstancePrototype(Object* value) { | 5599 Object* JSFunction::SetInstancePrototype(Object* value) { |
| 5500 ASSERT(value->IsJSObject()); | 5600 ASSERT(value->IsJSObject()); |
| 5501 | 5601 Heap* heap = GetHeap(); |
| 5502 if (has_initial_map()) { | 5602 if (has_initial_map()) { |
| 5503 initial_map()->set_prototype(value); | 5603 initial_map()->set_prototype(value); |
| 5504 } else { | 5604 } else { |
| 5505 // Put the value in the initial map field until an initial map is | 5605 // Put the value in the initial map field until an initial map is |
| 5506 // needed. At that point, a new initial map is created and the | 5606 // needed. At that point, a new initial map is created and the |
| 5507 // prototype is put into the initial map where it belongs. | 5607 // prototype is put into the initial map where it belongs. |
| 5508 set_prototype_or_initial_map(value); | 5608 set_prototype_or_initial_map(value); |
| 5509 } | 5609 } |
| 5510 Heap::ClearInstanceofCache(); | 5610 heap->ClearInstanceofCache(); |
| 5511 return value; | 5611 return value; |
| 5512 } | 5612 } |
| 5513 | 5613 |
| 5514 | 5614 |
| 5515 MaybeObject* JSFunction::SetPrototype(Object* value) { | 5615 MaybeObject* JSFunction::SetPrototype(Object* value) { |
| 5516 ASSERT(should_have_prototype()); | 5616 ASSERT(should_have_prototype()); |
| 5517 Object* construct_prototype = value; | 5617 Object* construct_prototype = value; |
| 5518 | 5618 |
| 5519 // If the value is not a JSObject, store the value in the map's | 5619 // If the value is not a JSObject, store the value in the map's |
| 5520 // constructor field so it can be accessed. Also, set the prototype | 5620 // constructor field so it can be accessed. Also, set the prototype |
| 5521 // used for constructing objects to the original object prototype. | 5621 // used for constructing objects to the original object prototype. |
| 5522 // See ECMA-262 13.2.2. | 5622 // See ECMA-262 13.2.2. |
| 5523 if (!value->IsJSObject()) { | 5623 if (!value->IsJSObject()) { |
| 5624 Heap* heap = GetHeap(); |
| 5524 // Copy the map so this does not affect unrelated functions. | 5625 // Copy the map so this does not affect unrelated functions. |
| 5525 // Remove map transitions because they point to maps with a | 5626 // Remove map transitions because they point to maps with a |
| 5526 // different prototype. | 5627 // different prototype. |
| 5527 Object* new_map; | 5628 Object* new_map; |
| 5528 { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); | 5629 { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); |
| 5529 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 5630 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 5530 } | 5631 } |
| 5531 set_map(Map::cast(new_map)); | 5632 set_map(Map::cast(new_map)); |
| 5532 map()->set_constructor(value); | 5633 map()->set_constructor(value); |
| 5533 map()->set_non_instance_prototype(true); | 5634 map()->set_non_instance_prototype(true); |
| 5534 construct_prototype = | 5635 construct_prototype = |
| 5535 Top::context()->global_context()->initial_object_prototype(); | 5636 heap->isolate()->context()->global_context()-> |
| 5637 initial_object_prototype(); |
| 5536 } else { | 5638 } else { |
| 5537 map()->set_non_instance_prototype(false); | 5639 map()->set_non_instance_prototype(false); |
| 5538 } | 5640 } |
| 5539 | 5641 |
| 5540 return SetInstancePrototype(construct_prototype); | 5642 return SetInstancePrototype(construct_prototype); |
| 5541 } | 5643 } |
| 5542 | 5644 |
| 5543 | 5645 |
| 5544 Object* JSFunction::RemovePrototype() { | 5646 Object* JSFunction::RemovePrototype() { |
| 5545 Context* global_context = context()->global_context(); | 5647 Context* global_context = context()->global_context(); |
| 5546 Map* no_prototype_map = shared()->strict_mode() | 5648 Map* no_prototype_map = shared()->strict_mode() |
| 5547 ? global_context->strict_mode_function_without_prototype_map() | 5649 ? global_context->strict_mode_function_without_prototype_map() |
| 5548 : global_context->function_without_prototype_map(); | 5650 : global_context->function_without_prototype_map(); |
| 5549 | 5651 |
| 5550 if (map() == no_prototype_map) { | 5652 if (map() == no_prototype_map) { |
| 5551 // Be idempotent. | 5653 // Be idempotent. |
| 5552 return this; | 5654 return this; |
| 5553 } | 5655 } |
| 5554 | 5656 |
| 5555 ASSERT(!shared()->strict_mode() || | 5657 ASSERT(!shared()->strict_mode() || |
| 5556 map() == global_context->strict_mode_function_map()); | 5658 map() == global_context->strict_mode_function_map()); |
| 5557 ASSERT(shared()->strict_mode() || map() == global_context->function_map()); | 5659 ASSERT(shared()->strict_mode() || map() == global_context->function_map()); |
| 5558 | 5660 |
| 5559 set_map(no_prototype_map); | 5661 set_map(no_prototype_map); |
| 5560 set_prototype_or_initial_map(Heap::the_hole_value()); | 5662 set_prototype_or_initial_map(GetHeap()->the_hole_value()); |
| 5561 return this; | 5663 return this; |
| 5562 } | 5664 } |
| 5563 | 5665 |
| 5564 | 5666 |
| 5565 Object* JSFunction::SetInstanceClassName(String* name) { | 5667 Object* JSFunction::SetInstanceClassName(String* name) { |
| 5566 shared()->set_instance_class_name(name); | 5668 shared()->set_instance_class_name(name); |
| 5567 return this; | 5669 return this; |
| 5568 } | 5670 } |
| 5569 | 5671 |
| 5570 | 5672 |
| 5571 void JSFunction::PrintName(FILE* out) { | 5673 void JSFunction::PrintName(FILE* out) { |
| 5572 SmartPointer<char> name = shared()->DebugName()->ToCString(); | 5674 SmartPointer<char> name = shared()->DebugName()->ToCString(); |
| 5573 PrintF(out, "%s", *name); | 5675 PrintF(out, "%s", *name); |
| 5574 } | 5676 } |
| 5575 | 5677 |
| 5576 | 5678 |
| 5577 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) { | 5679 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) { |
| 5578 return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex)); | 5680 return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex)); |
| 5579 } | 5681 } |
| 5580 | 5682 |
| 5581 | 5683 |
| 5582 MaybeObject* Oddball::Initialize(const char* to_string, Object* to_number) { | 5684 MaybeObject* Oddball::Initialize(const char* to_string, |
| 5685 Object* to_number, |
| 5686 byte kind) { |
| 5583 Object* symbol; | 5687 Object* symbol; |
| 5584 { MaybeObject* maybe_symbol = Heap::LookupAsciiSymbol(to_string); | 5688 { MaybeObject* maybe_symbol = |
| 5689 Isolate::Current()->heap()->LookupAsciiSymbol(to_string); |
| 5585 if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol; | 5690 if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol; |
| 5586 } | 5691 } |
| 5587 set_to_string(String::cast(symbol)); | 5692 set_to_string(String::cast(symbol)); |
| 5588 set_to_number(to_number); | 5693 set_to_number(to_number); |
| 5694 set_kind(kind); |
| 5589 return this; | 5695 return this; |
| 5590 } | 5696 } |
| 5591 | 5697 |
| 5592 | 5698 |
| 5593 String* SharedFunctionInfo::DebugName() { | 5699 String* SharedFunctionInfo::DebugName() { |
| 5594 Object* n = name(); | 5700 Object* n = name(); |
| 5595 if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name(); | 5701 if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name(); |
| 5596 return String::cast(n); | 5702 return String::cast(n); |
| 5597 } | 5703 } |
| 5598 | 5704 |
| 5599 | 5705 |
| 5600 bool SharedFunctionInfo::HasSourceCode() { | 5706 bool SharedFunctionInfo::HasSourceCode() { |
| 5601 return !script()->IsUndefined() && | 5707 return !script()->IsUndefined() && |
| 5602 !reinterpret_cast<Script*>(script())->source()->IsUndefined(); | 5708 !reinterpret_cast<Script*>(script())->source()->IsUndefined(); |
| 5603 } | 5709 } |
| 5604 | 5710 |
| 5605 | 5711 |
| 5606 Object* SharedFunctionInfo::GetSourceCode() { | 5712 Object* SharedFunctionInfo::GetSourceCode() { |
| 5607 if (!HasSourceCode()) return Heap::undefined_value(); | 5713 Isolate* isolate = GetIsolate(); |
| 5608 HandleScope scope; | 5714 if (!HasSourceCode()) return isolate->heap()->undefined_value(); |
| 5715 HandleScope scope(isolate); |
| 5609 Object* source = Script::cast(script())->source(); | 5716 Object* source = Script::cast(script())->source(); |
| 5610 return *SubString(Handle<String>(String::cast(source)), | 5717 return *SubString(Handle<String>(String::cast(source), isolate), |
| 5611 start_position(), end_position()); | 5718 start_position(), end_position()); |
| 5612 } | 5719 } |
| 5613 | 5720 |
| 5614 | 5721 |
| 5615 int SharedFunctionInfo::SourceSize() { | 5722 int SharedFunctionInfo::SourceSize() { |
| 5616 return end_position() - start_position(); | 5723 return end_position() - start_position(); |
| 5617 } | 5724 } |
| 5618 | 5725 |
| 5619 | 5726 |
| 5620 int SharedFunctionInfo::CalculateInstanceSize() { | 5727 int SharedFunctionInfo::CalculateInstanceSize() { |
| 5621 int instance_size = | 5728 int instance_size = |
| 5622 JSObject::kHeaderSize + | 5729 JSObject::kHeaderSize + |
| 5623 expected_nof_properties() * kPointerSize; | 5730 expected_nof_properties() * kPointerSize; |
| 5624 if (instance_size > JSObject::kMaxInstanceSize) { | 5731 if (instance_size > JSObject::kMaxInstanceSize) { |
| 5625 instance_size = JSObject::kMaxInstanceSize; | 5732 instance_size = JSObject::kMaxInstanceSize; |
| 5626 } | 5733 } |
| 5627 return instance_size; | 5734 return instance_size; |
| 5628 } | 5735 } |
| 5629 | 5736 |
| 5630 | 5737 |
| 5631 int SharedFunctionInfo::CalculateInObjectProperties() { | 5738 int SharedFunctionInfo::CalculateInObjectProperties() { |
| 5632 return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize; | 5739 return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize; |
| 5633 } | 5740 } |
| 5634 | 5741 |
| 5635 | 5742 |
| 5636 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) { | 5743 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) { |
| 5744 Heap* heap = GetHeap(); |
| 5745 |
| 5637 // Check the basic conditions for generating inline constructor code. | 5746 // Check the basic conditions for generating inline constructor code. |
| 5638 if (!FLAG_inline_new | 5747 if (!FLAG_inline_new |
| 5639 || !has_only_simple_this_property_assignments() | 5748 || !has_only_simple_this_property_assignments() |
| 5640 || this_property_assignments_count() == 0) { | 5749 || this_property_assignments_count() == 0) { |
| 5641 return false; | 5750 return false; |
| 5642 } | 5751 } |
| 5643 | 5752 |
| 5644 // If the prototype is null inline constructors cause no problems. | 5753 // If the prototype is null inline constructors cause no problems. |
| 5645 if (!prototype->IsJSObject()) { | 5754 if (!prototype->IsJSObject()) { |
| 5646 ASSERT(prototype->IsNull()); | 5755 ASSERT(prototype->IsNull()); |
| 5647 return true; | 5756 return true; |
| 5648 } | 5757 } |
| 5649 | 5758 |
| 5650 // Traverse the proposed prototype chain looking for setters for properties of | 5759 // Traverse the proposed prototype chain looking for setters for properties of |
| 5651 // the same names as are set by the inline constructor. | 5760 // the same names as are set by the inline constructor. |
| 5652 for (Object* obj = prototype; | 5761 for (Object* obj = prototype; |
| 5653 obj != Heap::null_value(); | 5762 obj != heap->null_value(); |
| 5654 obj = obj->GetPrototype()) { | 5763 obj = obj->GetPrototype()) { |
| 5655 JSObject* js_object = JSObject::cast(obj); | 5764 JSObject* js_object = JSObject::cast(obj); |
| 5656 for (int i = 0; i < this_property_assignments_count(); i++) { | 5765 for (int i = 0; i < this_property_assignments_count(); i++) { |
| 5657 LookupResult result; | 5766 LookupResult result; |
| 5658 String* name = GetThisPropertyAssignmentName(i); | 5767 String* name = GetThisPropertyAssignmentName(i); |
| 5659 js_object->LocalLookupRealNamedProperty(name, &result); | 5768 js_object->LocalLookupRealNamedProperty(name, &result); |
| 5660 if (result.IsProperty() && result.type() == CALLBACKS) { | 5769 if (result.IsProperty() && result.type() == CALLBACKS) { |
| 5661 return false; | 5770 return false; |
| 5662 } | 5771 } |
| 5663 } | 5772 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5679 FixedArray* assignments) { | 5788 FixedArray* assignments) { |
| 5680 set_compiler_hints(BooleanBit::set(compiler_hints(), | 5789 set_compiler_hints(BooleanBit::set(compiler_hints(), |
| 5681 kHasOnlySimpleThisPropertyAssignments, | 5790 kHasOnlySimpleThisPropertyAssignments, |
| 5682 only_simple_this_property_assignments)); | 5791 only_simple_this_property_assignments)); |
| 5683 set_this_property_assignments(assignments); | 5792 set_this_property_assignments(assignments); |
| 5684 set_this_property_assignments_count(assignments->length() / 3); | 5793 set_this_property_assignments_count(assignments->length() / 3); |
| 5685 } | 5794 } |
| 5686 | 5795 |
| 5687 | 5796 |
| 5688 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() { | 5797 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() { |
| 5798 Heap* heap = GetHeap(); |
| 5689 set_compiler_hints(BooleanBit::set(compiler_hints(), | 5799 set_compiler_hints(BooleanBit::set(compiler_hints(), |
| 5690 kHasOnlySimpleThisPropertyAssignments, | 5800 kHasOnlySimpleThisPropertyAssignments, |
| 5691 false)); | 5801 false)); |
| 5692 set_this_property_assignments(Heap::undefined_value()); | 5802 set_this_property_assignments(heap->undefined_value()); |
| 5693 set_this_property_assignments_count(0); | 5803 set_this_property_assignments_count(0); |
| 5694 } | 5804 } |
| 5695 | 5805 |
| 5696 | 5806 |
| 5697 String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) { | 5807 String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) { |
| 5698 Object* obj = this_property_assignments(); | 5808 Object* obj = this_property_assignments(); |
| 5699 ASSERT(obj->IsFixedArray()); | 5809 ASSERT(obj->IsFixedArray()); |
| 5700 ASSERT(index < this_property_assignments_count()); | 5810 ASSERT(index < this_property_assignments_count()); |
| 5701 obj = FixedArray::cast(obj)->get(index * 3); | 5811 obj = FixedArray::cast(obj)->get(index * 3); |
| 5702 ASSERT(obj->IsString()); | 5812 ASSERT(obj->IsString()); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5827 if (Serializer::enabled()) return; | 5937 if (Serializer::enabled()) return; |
| 5828 | 5938 |
| 5829 if (map->unused_property_fields() == 0) return; | 5939 if (map->unused_property_fields() == 0) return; |
| 5830 | 5940 |
| 5831 // Nonzero counter is a leftover from the previous attempt interrupted | 5941 // Nonzero counter is a leftover from the previous attempt interrupted |
| 5832 // by GC, keep it. | 5942 // by GC, keep it. |
| 5833 if (construction_count() == 0) { | 5943 if (construction_count() == 0) { |
| 5834 set_construction_count(kGenerousAllocationCount); | 5944 set_construction_count(kGenerousAllocationCount); |
| 5835 } | 5945 } |
| 5836 set_initial_map(map); | 5946 set_initial_map(map); |
| 5837 ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubGeneric), | 5947 Builtins* builtins = map->heap()->isolate()->builtins(); |
| 5948 ASSERT_EQ(builtins->builtin(Builtins::JSConstructStubGeneric), |
| 5838 construct_stub()); | 5949 construct_stub()); |
| 5839 set_construct_stub(Builtins::builtin(Builtins::JSConstructStubCountdown)); | 5950 set_construct_stub(builtins->builtin(Builtins::JSConstructStubCountdown)); |
| 5840 } | 5951 } |
| 5841 | 5952 |
| 5842 | 5953 |
| 5843 // Called from GC, hence reinterpret_cast and unchecked accessors. | 5954 // Called from GC, hence reinterpret_cast and unchecked accessors. |
| 5844 void SharedFunctionInfo::DetachInitialMap() { | 5955 void SharedFunctionInfo::DetachInitialMap() { |
| 5845 Map* map = reinterpret_cast<Map*>(initial_map()); | 5956 Map* map = reinterpret_cast<Map*>(initial_map()); |
| 5846 | 5957 |
| 5847 // Make the map remember to restore the link if it survives the GC. | 5958 // Make the map remember to restore the link if it survives the GC. |
| 5848 map->set_bit_field2( | 5959 map->set_bit_field2( |
| 5849 map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo)); | 5960 map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo)); |
| 5850 | 5961 |
| 5851 // Undo state changes made by StartInobjectTracking (except the | 5962 // Undo state changes made by StartInobjectTracking (except the |
| 5852 // construction_count). This way if the initial map does not survive the GC | 5963 // construction_count). This way if the initial map does not survive the GC |
| 5853 // then StartInobjectTracking will be called again the next time the | 5964 // then StartInobjectTracking will be called again the next time the |
| 5854 // constructor is called. The countdown will continue and (possibly after | 5965 // constructor is called. The countdown will continue and (possibly after |
| 5855 // several more GCs) CompleteInobjectSlackTracking will eventually be called. | 5966 // several more GCs) CompleteInobjectSlackTracking will eventually be called. |
| 5856 set_initial_map(Heap::raw_unchecked_undefined_value()); | 5967 set_initial_map(map->heap()->raw_unchecked_undefined_value()); |
| 5857 ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubCountdown), | 5968 Builtins* builtins = map->heap()->isolate()->builtins(); |
| 5969 ASSERT_EQ(builtins->builtin(Builtins::JSConstructStubCountdown), |
| 5858 *RawField(this, kConstructStubOffset)); | 5970 *RawField(this, kConstructStubOffset)); |
| 5859 set_construct_stub(Builtins::builtin(Builtins::JSConstructStubGeneric)); | 5971 set_construct_stub(builtins->builtin(Builtins::JSConstructStubGeneric)); |
| 5860 // It is safe to clear the flag: it will be set again if the map is live. | 5972 // It is safe to clear the flag: it will be set again if the map is live. |
| 5861 set_live_objects_may_exist(false); | 5973 set_live_objects_may_exist(false); |
| 5862 } | 5974 } |
| 5863 | 5975 |
| 5864 | 5976 |
| 5865 // Called from GC, hence reinterpret_cast and unchecked accessors. | 5977 // Called from GC, hence reinterpret_cast and unchecked accessors. |
| 5866 void SharedFunctionInfo::AttachInitialMap(Map* map) { | 5978 void SharedFunctionInfo::AttachInitialMap(Map* map) { |
| 5867 map->set_bit_field2( | 5979 map->set_bit_field2( |
| 5868 map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo)); | 5980 map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo)); |
| 5869 | 5981 |
| 5870 // Resume inobject slack tracking. | 5982 // Resume inobject slack tracking. |
| 5871 set_initial_map(map); | 5983 set_initial_map(map); |
| 5872 ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubGeneric), | 5984 Builtins* builtins = map->heap()->isolate()->builtins(); |
| 5985 ASSERT_EQ(builtins->builtin(Builtins::JSConstructStubGeneric), |
| 5873 *RawField(this, kConstructStubOffset)); | 5986 *RawField(this, kConstructStubOffset)); |
| 5874 set_construct_stub(Builtins::builtin(Builtins::JSConstructStubCountdown)); | 5987 set_construct_stub(builtins->builtin(Builtins::JSConstructStubCountdown)); |
| 5875 // The map survived the gc, so there may be objects referencing it. | 5988 // The map survived the gc, so there may be objects referencing it. |
| 5876 set_live_objects_may_exist(true); | 5989 set_live_objects_may_exist(true); |
| 5877 } | 5990 } |
| 5878 | 5991 |
| 5879 | 5992 |
| 5880 static void GetMinInobjectSlack(Map* map, void* data) { | 5993 static void GetMinInobjectSlack(Map* map, void* data) { |
| 5881 int slack = map->unused_property_fields(); | 5994 int slack = map->unused_property_fields(); |
| 5882 if (*reinterpret_cast<int*>(data) > slack) { | 5995 if (*reinterpret_cast<int*>(data) > slack) { |
| 5883 *reinterpret_cast<int*>(data) = slack; | 5996 *reinterpret_cast<int*>(data) = slack; |
| 5884 } | 5997 } |
| 5885 } | 5998 } |
| 5886 | 5999 |
| 5887 | 6000 |
| 5888 static void ShrinkInstanceSize(Map* map, void* data) { | 6001 static void ShrinkInstanceSize(Map* map, void* data) { |
| 5889 int slack = *reinterpret_cast<int*>(data); | 6002 int slack = *reinterpret_cast<int*>(data); |
| 5890 map->set_inobject_properties(map->inobject_properties() - slack); | 6003 map->set_inobject_properties(map->inobject_properties() - slack); |
| 5891 map->set_unused_property_fields(map->unused_property_fields() - slack); | 6004 map->set_unused_property_fields(map->unused_property_fields() - slack); |
| 5892 map->set_instance_size(map->instance_size() - slack * kPointerSize); | 6005 map->set_instance_size(map->instance_size() - slack * kPointerSize); |
| 5893 | 6006 |
| 5894 // Visitor id might depend on the instance size, recalculate it. | 6007 // Visitor id might depend on the instance size, recalculate it. |
| 5895 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); | 6008 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); |
| 5896 } | 6009 } |
| 5897 | 6010 |
| 5898 | 6011 |
| 5899 void SharedFunctionInfo::CompleteInobjectSlackTracking() { | 6012 void SharedFunctionInfo::CompleteInobjectSlackTracking() { |
| 5900 ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress()); | 6013 ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress()); |
| 5901 Map* map = Map::cast(initial_map()); | 6014 Map* map = Map::cast(initial_map()); |
| 5902 | 6015 |
| 5903 set_initial_map(Heap::undefined_value()); | 6016 Heap* heap = map->heap(); |
| 5904 ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubCountdown), | 6017 set_initial_map(heap->undefined_value()); |
| 6018 Builtins* builtins = heap->isolate()->builtins(); |
| 6019 ASSERT_EQ(builtins->builtin(Builtins::JSConstructStubCountdown), |
| 5905 construct_stub()); | 6020 construct_stub()); |
| 5906 set_construct_stub(Builtins::builtin(Builtins::JSConstructStubGeneric)); | 6021 set_construct_stub(builtins->builtin(Builtins::JSConstructStubGeneric)); |
| 5907 | 6022 |
| 5908 int slack = map->unused_property_fields(); | 6023 int slack = map->unused_property_fields(); |
| 5909 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); | 6024 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); |
| 5910 if (slack != 0) { | 6025 if (slack != 0) { |
| 5911 // Resize the initial map and all maps in its transition tree. | 6026 // Resize the initial map and all maps in its transition tree. |
| 5912 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); | 6027 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); |
| 5913 // Give the correct expected_nof_properties to initial maps created later. | 6028 // Give the correct expected_nof_properties to initial maps created later. |
| 5914 ASSERT(expected_nof_properties() >= slack); | 6029 ASSERT(expected_nof_properties() >= slack); |
| 5915 set_expected_nof_properties(expected_nof_properties() - slack); | 6030 set_expected_nof_properties(expected_nof_properties() - slack); |
| 5916 } | 6031 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5953 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 6068 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 5954 rinfo->IsPatchedDebugBreakSlotSequence())); | 6069 rinfo->IsPatchedDebugBreakSlotSequence())); |
| 5955 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 6070 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 5956 Object* old_target = target; | 6071 Object* old_target = target; |
| 5957 VisitPointer(&target); | 6072 VisitPointer(&target); |
| 5958 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. | 6073 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 5959 } | 6074 } |
| 5960 | 6075 |
| 5961 | 6076 |
| 5962 void Code::InvalidateRelocation() { | 6077 void Code::InvalidateRelocation() { |
| 5963 HandleScope scope; | 6078 set_relocation_info(GetHeap()->empty_byte_array()); |
| 5964 set_relocation_info(Heap::empty_byte_array()); | |
| 5965 } | 6079 } |
| 5966 | 6080 |
| 5967 | 6081 |
| 5968 void Code::Relocate(intptr_t delta) { | 6082 void Code::Relocate(intptr_t delta) { |
| 5969 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { | 6083 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { |
| 5970 it.rinfo()->apply(delta); | 6084 it.rinfo()->apply(delta); |
| 5971 } | 6085 } |
| 5972 CPU::FlushICache(instruction_start(), instruction_size()); | 6086 CPU::FlushICache(instruction_start(), instruction_size()); |
| 5973 } | 6087 } |
| 5974 | 6088 |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6400 | 6514 |
| 6401 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 6515 PrintF("RelocInfo (size = %d)\n", relocation_size()); |
| 6402 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); | 6516 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); |
| 6403 PrintF(out, "\n"); | 6517 PrintF(out, "\n"); |
| 6404 } | 6518 } |
| 6405 #endif // ENABLE_DISASSEMBLER | 6519 #endif // ENABLE_DISASSEMBLER |
| 6406 | 6520 |
| 6407 | 6521 |
| 6408 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, | 6522 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, |
| 6409 int length) { | 6523 int length) { |
| 6524 Heap* heap = GetHeap(); |
| 6410 // We should never end in here with a pixel or external array. | 6525 // We should never end in here with a pixel or external array. |
| 6411 ASSERT(!HasExternalArrayElements()); | 6526 ASSERT(!HasExternalArrayElements()); |
| 6412 | 6527 |
| 6413 Object* obj; | 6528 Object* obj; |
| 6414 { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(capacity); | 6529 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); |
| 6415 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6530 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6416 } | 6531 } |
| 6417 FixedArray* elems = FixedArray::cast(obj); | 6532 FixedArray* elems = FixedArray::cast(obj); |
| 6418 | 6533 |
| 6419 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); | 6534 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); |
| 6420 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6535 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6421 } | 6536 } |
| 6422 Map* new_map = Map::cast(obj); | 6537 Map* new_map = Map::cast(obj); |
| 6423 | 6538 |
| 6424 AssertNoAllocation no_gc; | 6539 AssertNoAllocation no_gc; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6491 } | 6606 } |
| 6492 default: | 6607 default: |
| 6493 UNREACHABLE(); | 6608 UNREACHABLE(); |
| 6494 break; | 6609 break; |
| 6495 } | 6610 } |
| 6496 return this; | 6611 return this; |
| 6497 } | 6612 } |
| 6498 | 6613 |
| 6499 | 6614 |
| 6500 MaybeObject* JSArray::Initialize(int capacity) { | 6615 MaybeObject* JSArray::Initialize(int capacity) { |
| 6616 Heap* heap = GetHeap(); |
| 6501 ASSERT(capacity >= 0); | 6617 ASSERT(capacity >= 0); |
| 6502 set_length(Smi::FromInt(0)); | 6618 set_length(Smi::FromInt(0)); |
| 6503 FixedArray* new_elements; | 6619 FixedArray* new_elements; |
| 6504 if (capacity == 0) { | 6620 if (capacity == 0) { |
| 6505 new_elements = Heap::empty_fixed_array(); | 6621 new_elements = heap->empty_fixed_array(); |
| 6506 } else { | 6622 } else { |
| 6507 Object* obj; | 6623 Object* obj; |
| 6508 { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(capacity); | 6624 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); |
| 6509 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6625 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6510 } | 6626 } |
| 6511 new_elements = FixedArray::cast(obj); | 6627 new_elements = FixedArray::cast(obj); |
| 6512 } | 6628 } |
| 6513 set_elements(new_elements); | 6629 set_elements(new_elements); |
| 6514 return this; | 6630 return this; |
| 6515 } | 6631 } |
| 6516 | 6632 |
| 6517 | 6633 |
| 6518 void JSArray::Expand(int required_size) { | 6634 void JSArray::Expand(int required_size) { |
| 6519 Handle<JSArray> self(this); | 6635 Handle<JSArray> self(this); |
| 6520 Handle<FixedArray> old_backing(FixedArray::cast(elements())); | 6636 Handle<FixedArray> old_backing(FixedArray::cast(elements())); |
| 6521 int old_size = old_backing->length(); | 6637 int old_size = old_backing->length(); |
| 6522 int new_size = required_size > old_size ? required_size : old_size; | 6638 int new_size = required_size > old_size ? required_size : old_size; |
| 6523 Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size); | 6639 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); |
| 6524 // Can't use this any more now because we may have had a GC! | 6640 // Can't use this any more now because we may have had a GC! |
| 6525 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | 6641 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
| 6526 self->SetContent(*new_backing); | 6642 self->SetContent(*new_backing); |
| 6527 } | 6643 } |
| 6528 | 6644 |
| 6529 | 6645 |
| 6530 static Failure* ArrayLengthRangeError() { | 6646 static Failure* ArrayLengthRangeError(Heap* heap) { |
| 6531 HandleScope scope; | 6647 HandleScope scope; |
| 6532 return Top::Throw(*Factory::NewRangeError("invalid_array_length", | 6648 return heap->isolate()->Throw( |
| 6533 HandleVector<Object>(NULL, 0))); | 6649 *FACTORY->NewRangeError("invalid_array_length", |
| 6650 HandleVector<Object>(NULL, 0))); |
| 6534 } | 6651 } |
| 6535 | 6652 |
| 6536 | 6653 |
| 6537 MaybeObject* JSObject::SetElementsLength(Object* len) { | 6654 MaybeObject* JSObject::SetElementsLength(Object* len) { |
| 6655 Heap* heap = GetHeap(); |
| 6538 // We should never end in here with a pixel or external array. | 6656 // We should never end in here with a pixel or external array. |
| 6539 ASSERT(AllowsSetElementsLength()); | 6657 ASSERT(AllowsSetElementsLength()); |
| 6540 | 6658 |
| 6541 MaybeObject* maybe_smi_length = len->ToSmi(); | 6659 MaybeObject* maybe_smi_length = len->ToSmi(); |
| 6542 Object* smi_length = Smi::FromInt(0); | 6660 Object* smi_length = Smi::FromInt(0); |
| 6543 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 6661 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
| 6544 const int value = Smi::cast(smi_length)->value(); | 6662 const int value = Smi::cast(smi_length)->value(); |
| 6545 if (value < 0) return ArrayLengthRangeError(); | 6663 if (value < 0) return ArrayLengthRangeError(heap); |
| 6546 switch (GetElementsKind()) { | 6664 switch (GetElementsKind()) { |
| 6547 case FAST_ELEMENTS: { | 6665 case FAST_ELEMENTS: { |
| 6548 int old_capacity = FixedArray::cast(elements())->length(); | 6666 int old_capacity = FixedArray::cast(elements())->length(); |
| 6549 if (value <= old_capacity) { | 6667 if (value <= old_capacity) { |
| 6550 if (IsJSArray()) { | 6668 if (IsJSArray()) { |
| 6551 Object* obj; | 6669 Object* obj; |
| 6552 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 6670 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 6553 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6671 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6554 } | 6672 } |
| 6555 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | 6673 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6601 break; | 6719 break; |
| 6602 } | 6720 } |
| 6603 } | 6721 } |
| 6604 | 6722 |
| 6605 // General slow case. | 6723 // General slow case. |
| 6606 if (len->IsNumber()) { | 6724 if (len->IsNumber()) { |
| 6607 uint32_t length; | 6725 uint32_t length; |
| 6608 if (len->ToArrayIndex(&length)) { | 6726 if (len->ToArrayIndex(&length)) { |
| 6609 return SetSlowElements(len); | 6727 return SetSlowElements(len); |
| 6610 } else { | 6728 } else { |
| 6611 return ArrayLengthRangeError(); | 6729 return ArrayLengthRangeError(heap); |
| 6612 } | 6730 } |
| 6613 } | 6731 } |
| 6614 | 6732 |
| 6615 // len is not a number so make the array size one and | 6733 // len is not a number so make the array size one and |
| 6616 // set only element to len. | 6734 // set only element to len. |
| 6617 Object* obj; | 6735 Object* obj; |
| 6618 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(1); | 6736 { MaybeObject* maybe_obj = heap->AllocateFixedArray(1); |
| 6619 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6737 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6620 } | 6738 } |
| 6621 FixedArray::cast(obj)->set(0, len); | 6739 FixedArray::cast(obj)->set(0, len); |
| 6622 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); | 6740 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); |
| 6623 set_elements(FixedArray::cast(obj)); | 6741 set_elements(FixedArray::cast(obj)); |
| 6624 return this; | 6742 return this; |
| 6625 } | 6743 } |
| 6626 | 6744 |
| 6627 | 6745 |
| 6628 MaybeObject* JSObject::SetPrototype(Object* value, | 6746 MaybeObject* JSObject::SetPrototype(Object* value, |
| 6629 bool skip_hidden_prototypes) { | 6747 bool skip_hidden_prototypes) { |
| 6748 Heap* heap = GetHeap(); |
| 6630 // Silently ignore the change if value is not a JSObject or null. | 6749 // Silently ignore the change if value is not a JSObject or null. |
| 6631 // SpiderMonkey behaves this way. | 6750 // SpiderMonkey behaves this way. |
| 6632 if (!value->IsJSObject() && !value->IsNull()) return value; | 6751 if (!value->IsJSObject() && !value->IsNull()) return value; |
| 6633 | 6752 |
| 6634 // Before we can set the prototype we need to be sure | 6753 // Before we can set the prototype we need to be sure |
| 6635 // prototype cycles are prevented. | 6754 // prototype cycles are prevented. |
| 6636 // It is sufficient to validate that the receiver is not in the new prototype | 6755 // It is sufficient to validate that the receiver is not in the new prototype |
| 6637 // chain. | 6756 // chain. |
| 6638 for (Object* pt = value; pt != Heap::null_value(); pt = pt->GetPrototype()) { | 6757 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) { |
| 6639 if (JSObject::cast(pt) == this) { | 6758 if (JSObject::cast(pt) == this) { |
| 6640 // Cycle detected. | 6759 // Cycle detected. |
| 6641 HandleScope scope; | 6760 HandleScope scope; |
| 6642 return Top::Throw(*Factory::NewError("cyclic_proto", | 6761 return heap->isolate()->Throw( |
| 6643 HandleVector<Object>(NULL, 0))); | 6762 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0))); |
| 6644 } | 6763 } |
| 6645 } | 6764 } |
| 6646 | 6765 |
| 6647 JSObject* real_receiver = this; | 6766 JSObject* real_receiver = this; |
| 6648 | 6767 |
| 6649 if (skip_hidden_prototypes) { | 6768 if (skip_hidden_prototypes) { |
| 6650 // Find the first object in the chain whose prototype object is not | 6769 // Find the first object in the chain whose prototype object is not |
| 6651 // hidden and set the new prototype on that object. | 6770 // hidden and set the new prototype on that object. |
| 6652 Object* current_proto = real_receiver->GetPrototype(); | 6771 Object* current_proto = real_receiver->GetPrototype(); |
| 6653 while (current_proto->IsJSObject() && | 6772 while (current_proto->IsJSObject() && |
| 6654 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { | 6773 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { |
| 6655 real_receiver = JSObject::cast(current_proto); | 6774 real_receiver = JSObject::cast(current_proto); |
| 6656 current_proto = current_proto->GetPrototype(); | 6775 current_proto = current_proto->GetPrototype(); |
| 6657 } | 6776 } |
| 6658 } | 6777 } |
| 6659 | 6778 |
| 6660 // Set the new prototype of the object. | 6779 // Set the new prototype of the object. |
| 6661 Object* new_map; | 6780 Object* new_map; |
| 6662 { MaybeObject* maybe_new_map = real_receiver->map()->CopyDropTransitions(); | 6781 { MaybeObject* maybe_new_map = real_receiver->map()->CopyDropTransitions(); |
| 6663 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 6782 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 6664 } | 6783 } |
| 6665 Map::cast(new_map)->set_prototype(value); | 6784 Map::cast(new_map)->set_prototype(value); |
| 6666 real_receiver->set_map(Map::cast(new_map)); | 6785 real_receiver->set_map(Map::cast(new_map)); |
| 6667 | 6786 |
| 6668 Heap::ClearInstanceofCache(); | 6787 heap->ClearInstanceofCache(); |
| 6669 | 6788 |
| 6670 return value; | 6789 return value; |
| 6671 } | 6790 } |
| 6672 | 6791 |
| 6673 | 6792 |
| 6674 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { | 6793 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { |
| 6675 switch (GetElementsKind()) { | 6794 switch (GetElementsKind()) { |
| 6676 case FAST_ELEMENTS: { | 6795 case FAST_ELEMENTS: { |
| 6677 uint32_t length = IsJSArray() ? | 6796 uint32_t length = IsJSArray() ? |
| 6678 static_cast<uint32_t> | 6797 static_cast<uint32_t> |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6713 } | 6832 } |
| 6714 default: | 6833 default: |
| 6715 UNREACHABLE(); | 6834 UNREACHABLE(); |
| 6716 break; | 6835 break; |
| 6717 } | 6836 } |
| 6718 | 6837 |
| 6719 // Handle [] on String objects. | 6838 // Handle [] on String objects. |
| 6720 if (this->IsStringObjectWithCharacterAt(index)) return true; | 6839 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 6721 | 6840 |
| 6722 Object* pt = GetPrototype(); | 6841 Object* pt = GetPrototype(); |
| 6723 if (pt == Heap::null_value()) return false; | 6842 if (pt->IsNull()) return false; |
| 6724 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 6843 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| 6725 } | 6844 } |
| 6726 | 6845 |
| 6727 | 6846 |
| 6728 bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) { | 6847 bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) { |
| 6848 Isolate* isolate = GetIsolate(); |
| 6729 // Make sure that the top context does not change when doing | 6849 // Make sure that the top context does not change when doing |
| 6730 // callbacks or interceptor calls. | 6850 // callbacks or interceptor calls. |
| 6731 AssertNoContextChange ncc; | 6851 AssertNoContextChange ncc; |
| 6732 HandleScope scope; | 6852 HandleScope scope(isolate); |
| 6733 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 6853 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 6734 Handle<JSObject> receiver_handle(receiver); | 6854 Handle<JSObject> receiver_handle(receiver); |
| 6735 Handle<JSObject> holder_handle(this); | 6855 Handle<JSObject> holder_handle(this); |
| 6736 CustomArguments args(interceptor->data(), receiver, this); | 6856 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 6737 v8::AccessorInfo info(args.end()); | 6857 v8::AccessorInfo info(args.end()); |
| 6738 if (!interceptor->query()->IsUndefined()) { | 6858 if (!interceptor->query()->IsUndefined()) { |
| 6739 v8::IndexedPropertyQuery query = | 6859 v8::IndexedPropertyQuery query = |
| 6740 v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query()); | 6860 v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query()); |
| 6741 LOG(ApiIndexedPropertyAccess("interceptor-indexed-has", this, index)); | 6861 LOG(isolate, |
| 6862 ApiIndexedPropertyAccess("interceptor-indexed-has", this, index)); |
| 6742 v8::Handle<v8::Integer> result; | 6863 v8::Handle<v8::Integer> result; |
| 6743 { | 6864 { |
| 6744 // Leaving JavaScript. | 6865 // Leaving JavaScript. |
| 6745 VMState state(EXTERNAL); | 6866 VMState state(isolate, EXTERNAL); |
| 6746 result = query(index, info); | 6867 result = query(index, info); |
| 6747 } | 6868 } |
| 6748 if (!result.IsEmpty()) { | 6869 if (!result.IsEmpty()) { |
| 6749 ASSERT(result->IsInt32()); | 6870 ASSERT(result->IsInt32()); |
| 6750 return true; // absence of property is signaled by empty handle. | 6871 return true; // absence of property is signaled by empty handle. |
| 6751 } | 6872 } |
| 6752 } else if (!interceptor->getter()->IsUndefined()) { | 6873 } else if (!interceptor->getter()->IsUndefined()) { |
| 6753 v8::IndexedPropertyGetter getter = | 6874 v8::IndexedPropertyGetter getter = |
| 6754 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); | 6875 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); |
| 6755 LOG(ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index)); | 6876 LOG(isolate, |
| 6877 ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index)); |
| 6756 v8::Handle<v8::Value> result; | 6878 v8::Handle<v8::Value> result; |
| 6757 { | 6879 { |
| 6758 // Leaving JavaScript. | 6880 // Leaving JavaScript. |
| 6759 VMState state(EXTERNAL); | 6881 VMState state(isolate, EXTERNAL); |
| 6760 result = getter(index, info); | 6882 result = getter(index, info); |
| 6761 } | 6883 } |
| 6762 if (!result.IsEmpty()) return true; | 6884 if (!result.IsEmpty()) return true; |
| 6763 } | 6885 } |
| 6764 return holder_handle->HasElementPostInterceptor(*receiver_handle, index); | 6886 return holder_handle->HasElementPostInterceptor(*receiver_handle, index); |
| 6765 } | 6887 } |
| 6766 | 6888 |
| 6767 | 6889 |
| 6768 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { | 6890 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { |
| 6891 Heap* heap = GetHeap(); |
| 6892 |
| 6769 // Check access rights if needed. | 6893 // Check access rights if needed. |
| 6770 if (IsAccessCheckNeeded() && | 6894 if (IsAccessCheckNeeded() && |
| 6771 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 6895 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 6772 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6896 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6773 return UNDEFINED_ELEMENT; | 6897 return UNDEFINED_ELEMENT; |
| 6774 } | 6898 } |
| 6775 | 6899 |
| 6776 if (IsJSGlobalProxy()) { | 6900 if (IsJSGlobalProxy()) { |
| 6777 Object* proto = GetPrototype(); | 6901 Object* proto = GetPrototype(); |
| 6778 if (proto->IsNull()) return UNDEFINED_ELEMENT; | 6902 if (proto->IsNull()) return UNDEFINED_ELEMENT; |
| 6779 ASSERT(proto->IsJSGlobalObject()); | 6903 ASSERT(proto->IsJSGlobalObject()); |
| 6780 return JSObject::cast(proto)->HasLocalElement(index); | 6904 return JSObject::cast(proto)->HasLocalElement(index); |
| 6781 } | 6905 } |
| 6782 | 6906 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6829 default: | 6953 default: |
| 6830 UNREACHABLE(); | 6954 UNREACHABLE(); |
| 6831 break; | 6955 break; |
| 6832 } | 6956 } |
| 6833 | 6957 |
| 6834 return UNDEFINED_ELEMENT; | 6958 return UNDEFINED_ELEMENT; |
| 6835 } | 6959 } |
| 6836 | 6960 |
| 6837 | 6961 |
| 6838 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { | 6962 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
| 6963 Heap* heap = GetHeap(); |
| 6964 |
| 6839 // Check access rights if needed. | 6965 // Check access rights if needed. |
| 6840 if (IsAccessCheckNeeded() && | 6966 if (IsAccessCheckNeeded() && |
| 6841 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 6967 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 6842 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6968 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6843 return false; | 6969 return false; |
| 6844 } | 6970 } |
| 6845 | 6971 |
| 6846 // Check for lookup interceptor | 6972 // Check for lookup interceptor |
| 6847 if (HasIndexedInterceptor()) { | 6973 if (HasIndexedInterceptor()) { |
| 6848 return HasElementWithInterceptor(receiver, index); | 6974 return HasElementWithInterceptor(receiver, index); |
| 6849 } | 6975 } |
| 6850 | 6976 |
| 6851 switch (GetElementsKind()) { | 6977 switch (GetElementsKind()) { |
| 6852 case FAST_ELEMENTS: { | 6978 case FAST_ELEMENTS: { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6887 } | 7013 } |
| 6888 default: | 7014 default: |
| 6889 UNREACHABLE(); | 7015 UNREACHABLE(); |
| 6890 break; | 7016 break; |
| 6891 } | 7017 } |
| 6892 | 7018 |
| 6893 // Handle [] on String objects. | 7019 // Handle [] on String objects. |
| 6894 if (this->IsStringObjectWithCharacterAt(index)) return true; | 7020 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 6895 | 7021 |
| 6896 Object* pt = GetPrototype(); | 7022 Object* pt = GetPrototype(); |
| 6897 if (pt == Heap::null_value()) return false; | 7023 if (pt->IsNull()) return false; |
| 6898 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 7024 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| 6899 } | 7025 } |
| 6900 | 7026 |
| 6901 | 7027 |
| 6902 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, | 7028 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, |
| 6903 Object* value, | 7029 Object* value, |
| 6904 StrictModeFlag strict_mode, | 7030 StrictModeFlag strict_mode, |
| 6905 bool check_prototype) { | 7031 bool check_prototype) { |
| 7032 Isolate* isolate = GetIsolate(); |
| 6906 // Make sure that the top context does not change when doing | 7033 // Make sure that the top context does not change when doing |
| 6907 // callbacks or interceptor calls. | 7034 // callbacks or interceptor calls. |
| 6908 AssertNoContextChange ncc; | 7035 AssertNoContextChange ncc; |
| 6909 HandleScope scope; | 7036 HandleScope scope(isolate); |
| 6910 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 7037 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 6911 Handle<JSObject> this_handle(this); | 7038 Handle<JSObject> this_handle(this); |
| 6912 Handle<Object> value_handle(value); | 7039 Handle<Object> value_handle(value, isolate); |
| 6913 if (!interceptor->setter()->IsUndefined()) { | 7040 if (!interceptor->setter()->IsUndefined()) { |
| 6914 v8::IndexedPropertySetter setter = | 7041 v8::IndexedPropertySetter setter = |
| 6915 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); | 7042 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); |
| 6916 LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); | 7043 LOG(isolate, |
| 6917 CustomArguments args(interceptor->data(), this, this); | 7044 ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); |
| 7045 CustomArguments args(isolate, interceptor->data(), this, this); |
| 6918 v8::AccessorInfo info(args.end()); | 7046 v8::AccessorInfo info(args.end()); |
| 6919 v8::Handle<v8::Value> result; | 7047 v8::Handle<v8::Value> result; |
| 6920 { | 7048 { |
| 6921 // Leaving JavaScript. | 7049 // Leaving JavaScript. |
| 6922 VMState state(EXTERNAL); | 7050 VMState state(isolate, EXTERNAL); |
| 6923 result = setter(index, v8::Utils::ToLocal(value_handle), info); | 7051 result = setter(index, v8::Utils::ToLocal(value_handle), info); |
| 6924 } | 7052 } |
| 6925 RETURN_IF_SCHEDULED_EXCEPTION(); | 7053 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 6926 if (!result.IsEmpty()) return *value_handle; | 7054 if (!result.IsEmpty()) return *value_handle; |
| 6927 } | 7055 } |
| 6928 MaybeObject* raw_result = | 7056 MaybeObject* raw_result = |
| 6929 this_handle->SetElementWithoutInterceptor(index, | 7057 this_handle->SetElementWithoutInterceptor(index, |
| 6930 *value_handle, | 7058 *value_handle, |
| 6931 strict_mode, | 7059 strict_mode, |
| 6932 check_prototype); | 7060 check_prototype); |
| 6933 RETURN_IF_SCHEDULED_EXCEPTION(); | 7061 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 6934 return raw_result; | 7062 return raw_result; |
| 6935 } | 7063 } |
| 6936 | 7064 |
| 6937 | 7065 |
| 6938 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, | 7066 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, |
| 6939 Object* structure, | 7067 Object* structure, |
| 6940 uint32_t index, | 7068 uint32_t index, |
| 6941 Object* holder) { | 7069 Object* holder) { |
| 7070 Isolate* isolate = GetIsolate(); |
| 6942 ASSERT(!structure->IsProxy()); | 7071 ASSERT(!structure->IsProxy()); |
| 6943 | 7072 |
| 6944 // api style callbacks. | 7073 // api style callbacks. |
| 6945 if (structure->IsAccessorInfo()) { | 7074 if (structure->IsAccessorInfo()) { |
| 6946 AccessorInfo* data = AccessorInfo::cast(structure); | 7075 AccessorInfo* data = AccessorInfo::cast(structure); |
| 6947 Object* fun_obj = data->getter(); | 7076 Object* fun_obj = data->getter(); |
| 6948 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); | 7077 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); |
| 6949 HandleScope scope; | 7078 HandleScope scope(isolate); |
| 6950 Handle<JSObject> self(JSObject::cast(receiver)); | 7079 Handle<JSObject> self(JSObject::cast(receiver)); |
| 6951 Handle<JSObject> holder_handle(JSObject::cast(holder)); | 7080 Handle<JSObject> holder_handle(JSObject::cast(holder)); |
| 6952 Handle<Object> number = Factory::NewNumberFromUint(index); | 7081 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 6953 Handle<String> key(Factory::NumberToString(number)); | 7082 Handle<String> key(isolate->factory()->NumberToString(number)); |
| 6954 LOG(ApiNamedPropertyAccess("load", *self, *key)); | 7083 LOG(isolate, ApiNamedPropertyAccess("load", *self, *key)); |
| 6955 CustomArguments args(data->data(), *self, *holder_handle); | 7084 CustomArguments args(isolate, data->data(), *self, *holder_handle); |
| 6956 v8::AccessorInfo info(args.end()); | 7085 v8::AccessorInfo info(args.end()); |
| 6957 v8::Handle<v8::Value> result; | 7086 v8::Handle<v8::Value> result; |
| 6958 { | 7087 { |
| 6959 // Leaving JavaScript. | 7088 // Leaving JavaScript. |
| 6960 VMState state(EXTERNAL); | 7089 VMState state(isolate, EXTERNAL); |
| 6961 result = call_fun(v8::Utils::ToLocal(key), info); | 7090 result = call_fun(v8::Utils::ToLocal(key), info); |
| 6962 } | 7091 } |
| 6963 RETURN_IF_SCHEDULED_EXCEPTION(); | 7092 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 6964 if (result.IsEmpty()) return Heap::undefined_value(); | 7093 if (result.IsEmpty()) return isolate->heap()->undefined_value(); |
| 6965 return *v8::Utils::OpenHandle(*result); | 7094 return *v8::Utils::OpenHandle(*result); |
| 6966 } | 7095 } |
| 6967 | 7096 |
| 6968 // __defineGetter__ callback | 7097 // __defineGetter__ callback |
| 6969 if (structure->IsFixedArray()) { | 7098 if (structure->IsFixedArray()) { |
| 6970 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); | 7099 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); |
| 6971 if (getter->IsJSFunction()) { | 7100 if (getter->IsJSFunction()) { |
| 6972 return Object::GetPropertyWithDefinedGetter(receiver, | 7101 return Object::GetPropertyWithDefinedGetter(receiver, |
| 6973 JSFunction::cast(getter)); | 7102 JSFunction::cast(getter)); |
| 6974 } | 7103 } |
| 6975 // Getter is not a function. | 7104 // Getter is not a function. |
| 6976 return Heap::undefined_value(); | 7105 return isolate->heap()->undefined_value(); |
| 6977 } | 7106 } |
| 6978 | 7107 |
| 6979 UNREACHABLE(); | 7108 UNREACHABLE(); |
| 6980 return NULL; | 7109 return NULL; |
| 6981 } | 7110 } |
| 6982 | 7111 |
| 6983 | 7112 |
| 6984 MaybeObject* JSObject::SetElementWithCallback(Object* structure, | 7113 MaybeObject* JSObject::SetElementWithCallback(Object* structure, |
| 6985 uint32_t index, | 7114 uint32_t index, |
| 6986 Object* value, | 7115 Object* value, |
| 6987 JSObject* holder) { | 7116 JSObject* holder) { |
| 6988 HandleScope scope; | 7117 Isolate* isolate = GetIsolate(); |
| 7118 HandleScope scope(isolate); |
| 6989 | 7119 |
| 6990 // We should never get here to initialize a const with the hole | 7120 // We should never get here to initialize a const with the hole |
| 6991 // value since a const declaration would conflict with the setter. | 7121 // value since a const declaration would conflict with the setter. |
| 6992 ASSERT(!value->IsTheHole()); | 7122 ASSERT(!value->IsTheHole()); |
| 6993 Handle<Object> value_handle(value); | 7123 Handle<Object> value_handle(value, isolate); |
| 6994 | 7124 |
| 6995 // To accommodate both the old and the new api we switch on the | 7125 // To accommodate both the old and the new api we switch on the |
| 6996 // data structure used to store the callbacks. Eventually proxy | 7126 // data structure used to store the callbacks. Eventually proxy |
| 6997 // callbacks should be phased out. | 7127 // callbacks should be phased out. |
| 6998 ASSERT(!structure->IsProxy()); | 7128 ASSERT(!structure->IsProxy()); |
| 6999 | 7129 |
| 7000 if (structure->IsAccessorInfo()) { | 7130 if (structure->IsAccessorInfo()) { |
| 7001 // api style callbacks | 7131 // api style callbacks |
| 7002 AccessorInfo* data = AccessorInfo::cast(structure); | 7132 AccessorInfo* data = AccessorInfo::cast(structure); |
| 7003 Object* call_obj = data->setter(); | 7133 Object* call_obj = data->setter(); |
| 7004 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); | 7134 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); |
| 7005 if (call_fun == NULL) return value; | 7135 if (call_fun == NULL) return value; |
| 7006 Handle<Object> number = Factory::NewNumberFromUint(index); | 7136 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 7007 Handle<String> key(Factory::NumberToString(number)); | 7137 Handle<String> key(isolate->factory()->NumberToString(number)); |
| 7008 LOG(ApiNamedPropertyAccess("store", this, *key)); | 7138 LOG(isolate, ApiNamedPropertyAccess("store", this, *key)); |
| 7009 CustomArguments args(data->data(), this, JSObject::cast(holder)); | 7139 CustomArguments args(isolate, data->data(), this, JSObject::cast(holder)); |
| 7010 v8::AccessorInfo info(args.end()); | 7140 v8::AccessorInfo info(args.end()); |
| 7011 { | 7141 { |
| 7012 // Leaving JavaScript. | 7142 // Leaving JavaScript. |
| 7013 VMState state(EXTERNAL); | 7143 VMState state(isolate, EXTERNAL); |
| 7014 call_fun(v8::Utils::ToLocal(key), | 7144 call_fun(v8::Utils::ToLocal(key), |
| 7015 v8::Utils::ToLocal(value_handle), | 7145 v8::Utils::ToLocal(value_handle), |
| 7016 info); | 7146 info); |
| 7017 } | 7147 } |
| 7018 RETURN_IF_SCHEDULED_EXCEPTION(); | 7148 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7019 return *value_handle; | 7149 return *value_handle; |
| 7020 } | 7150 } |
| 7021 | 7151 |
| 7022 if (structure->IsFixedArray()) { | 7152 if (structure->IsFixedArray()) { |
| 7023 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); | 7153 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); |
| 7024 if (setter->IsJSFunction()) { | 7154 if (setter->IsJSFunction()) { |
| 7025 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); | 7155 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); |
| 7026 } else { | 7156 } else { |
| 7027 Handle<Object> holder_handle(holder); | 7157 Handle<Object> holder_handle(holder, isolate); |
| 7028 Handle<Object> key(Factory::NewNumberFromUint(index)); | 7158 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); |
| 7029 Handle<Object> args[2] = { key, holder_handle }; | 7159 Handle<Object> args[2] = { key, holder_handle }; |
| 7030 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback", | 7160 return isolate->Throw( |
| 7031 HandleVector(args, 2))); | 7161 *isolate->factory()->NewTypeError("no_setter_in_callback", |
| 7162 HandleVector(args, 2))); |
| 7032 } | 7163 } |
| 7033 } | 7164 } |
| 7034 | 7165 |
| 7035 UNREACHABLE(); | 7166 UNREACHABLE(); |
| 7036 return NULL; | 7167 return NULL; |
| 7037 } | 7168 } |
| 7038 | 7169 |
| 7039 | 7170 |
| 7040 // Adding n elements in fast case is O(n*n). | 7171 // Adding n elements in fast case is O(n*n). |
| 7041 // Note: revisit design to have dual undefined values to capture absent | 7172 // Note: revisit design to have dual undefined values to capture absent |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7100 } | 7231 } |
| 7101 ASSERT(HasDictionaryElements()); | 7232 ASSERT(HasDictionaryElements()); |
| 7102 return SetElement(index, value, strict_mode, check_prototype); | 7233 return SetElement(index, value, strict_mode, check_prototype); |
| 7103 } | 7234 } |
| 7104 | 7235 |
| 7105 | 7236 |
| 7106 MaybeObject* JSObject::SetElement(uint32_t index, | 7237 MaybeObject* JSObject::SetElement(uint32_t index, |
| 7107 Object* value, | 7238 Object* value, |
| 7108 StrictModeFlag strict_mode, | 7239 StrictModeFlag strict_mode, |
| 7109 bool check_prototype) { | 7240 bool check_prototype) { |
| 7241 Heap* heap = GetHeap(); |
| 7110 // Check access rights if needed. | 7242 // Check access rights if needed. |
| 7111 if (IsAccessCheckNeeded() && | 7243 if (IsAccessCheckNeeded() && |
| 7112 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 7244 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { |
| 7113 HandleScope scope; | 7245 HandleScope scope; |
| 7114 Handle<Object> value_handle(value); | 7246 Handle<Object> value_handle(value); |
| 7115 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 7247 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 7116 return *value_handle; | 7248 return *value_handle; |
| 7117 } | 7249 } |
| 7118 | 7250 |
| 7119 if (IsJSGlobalProxy()) { | 7251 if (IsJSGlobalProxy()) { |
| 7120 Object* proto = GetPrototype(); | 7252 Object* proto = GetPrototype(); |
| 7121 if (proto->IsNull()) return value; | 7253 if (proto->IsNull()) return value; |
| 7122 ASSERT(proto->IsJSGlobalObject()); | 7254 ASSERT(proto->IsJSGlobalObject()); |
| 7123 return JSObject::cast(proto)->SetElement(index, | 7255 return JSObject::cast(proto)->SetElement(index, |
| 7124 value, | 7256 value, |
| 7125 strict_mode, | 7257 strict_mode, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 7138 value, | 7270 value, |
| 7139 strict_mode, | 7271 strict_mode, |
| 7140 check_prototype); | 7272 check_prototype); |
| 7141 } | 7273 } |
| 7142 | 7274 |
| 7143 | 7275 |
| 7144 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 7276 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
| 7145 Object* value, | 7277 Object* value, |
| 7146 StrictModeFlag strict_mode, | 7278 StrictModeFlag strict_mode, |
| 7147 bool check_prototype) { | 7279 bool check_prototype) { |
| 7280 Isolate* isolate = GetIsolate(); |
| 7148 switch (GetElementsKind()) { | 7281 switch (GetElementsKind()) { |
| 7149 case FAST_ELEMENTS: | 7282 case FAST_ELEMENTS: |
| 7150 // Fast case. | 7283 // Fast case. |
| 7151 return SetFastElement(index, value, strict_mode, check_prototype); | 7284 return SetFastElement(index, value, strict_mode, check_prototype); |
| 7152 case EXTERNAL_PIXEL_ELEMENTS: { | 7285 case EXTERNAL_PIXEL_ELEMENTS: { |
| 7153 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 7286 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 7154 return pixels->SetValue(index, value); | 7287 return pixels->SetValue(index, value); |
| 7155 } | 7288 } |
| 7156 case EXTERNAL_BYTE_ELEMENTS: { | 7289 case EXTERNAL_BYTE_ELEMENTS: { |
| 7157 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 7290 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7193 if (entry != NumberDictionary::kNotFound) { | 7326 if (entry != NumberDictionary::kNotFound) { |
| 7194 Object* element = dictionary->ValueAt(entry); | 7327 Object* element = dictionary->ValueAt(entry); |
| 7195 PropertyDetails details = dictionary->DetailsAt(entry); | 7328 PropertyDetails details = dictionary->DetailsAt(entry); |
| 7196 if (details.type() == CALLBACKS) { | 7329 if (details.type() == CALLBACKS) { |
| 7197 return SetElementWithCallback(element, index, value, this); | 7330 return SetElementWithCallback(element, index, value, this); |
| 7198 } else { | 7331 } else { |
| 7199 dictionary->UpdateMaxNumberKey(index); | 7332 dictionary->UpdateMaxNumberKey(index); |
| 7200 // If put fails instrict mode, throw exception. | 7333 // If put fails instrict mode, throw exception. |
| 7201 if (!dictionary->ValueAtPut(entry, value) && | 7334 if (!dictionary->ValueAtPut(entry, value) && |
| 7202 strict_mode == kStrictMode) { | 7335 strict_mode == kStrictMode) { |
| 7203 Handle<Object> number(Factory::NewNumberFromUint(index)); | 7336 Handle<Object> number(isolate->factory()->NewNumberFromUint(index)); |
| 7204 Handle<Object> holder(this); | 7337 Handle<Object> holder(this); |
| 7205 Handle<Object> args[2] = { number, holder }; | 7338 Handle<Object> args[2] = { number, holder }; |
| 7206 return Top::Throw( | 7339 return isolate->Throw( |
| 7207 *Factory::NewTypeError("strict_read_only_property", | 7340 *isolate->factory()->NewTypeError("strict_read_only_property", |
| 7208 HandleVector(args, 2))); | 7341 HandleVector(args, 2))); |
| 7209 } | 7342 } |
| 7210 } | 7343 } |
| 7211 } else { | 7344 } else { |
| 7212 // Index not already used. Look for an accessor in the prototype chain. | 7345 // Index not already used. Look for an accessor in the prototype chain. |
| 7213 if (check_prototype) { | 7346 if (check_prototype) { |
| 7214 bool found; | 7347 bool found; |
| 7215 MaybeObject* result = | 7348 MaybeObject* result = |
| 7216 // Strict mode not needed. No-setter case already handled. | 7349 // Strict mode not needed. No-setter case already handled. |
| 7217 SetElementWithCallbackSetterInPrototypes(index, value, &found); | 7350 SetElementWithCallbackSetterInPrototypes(index, value, &found); |
| 7218 if (found) return result; | 7351 if (found) return result; |
| 7219 } | 7352 } |
| 7220 // When we set the is_extensible flag to false we always force | 7353 // When we set the is_extensible flag to false we always force |
| 7221 // the element into dictionary mode (and force them to stay there). | 7354 // the element into dictionary mode (and force them to stay there). |
| 7222 if (!map()->is_extensible()) { | 7355 if (!map()->is_extensible()) { |
| 7223 Handle<Object> number(Factory::NewNumberFromUint(index)); | 7356 Handle<Object> number(isolate->factory()->NewNumberFromUint(index)); |
| 7224 Handle<String> index_string(Factory::NumberToString(number)); | 7357 Handle<String> index_string( |
| 7358 isolate->factory()->NumberToString(number)); |
| 7225 Handle<Object> args[1] = { index_string }; | 7359 Handle<Object> args[1] = { index_string }; |
| 7226 return Top::Throw(*Factory::NewTypeError("object_not_extensible", | 7360 return isolate->Throw( |
| 7227 HandleVector(args, 1))); | 7361 *isolate->factory()->NewTypeError("object_not_extensible", |
| 7362 HandleVector(args, 1))); |
| 7228 } | 7363 } |
| 7229 Object* result; | 7364 Object* result; |
| 7230 { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value); | 7365 { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value); |
| 7231 if (!maybe_result->ToObject(&result)) return maybe_result; | 7366 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 7232 } | 7367 } |
| 7233 if (elms != FixedArray::cast(result)) { | 7368 if (elms != FixedArray::cast(result)) { |
| 7234 set_elements(FixedArray::cast(result)); | 7369 set_elements(FixedArray::cast(result)); |
| 7235 } | 7370 } |
| 7236 } | 7371 } |
| 7237 | 7372 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7270 | 7405 |
| 7271 return value; | 7406 return value; |
| 7272 } | 7407 } |
| 7273 default: | 7408 default: |
| 7274 UNREACHABLE(); | 7409 UNREACHABLE(); |
| 7275 break; | 7410 break; |
| 7276 } | 7411 } |
| 7277 // All possible cases have been handled above. Add a return to avoid the | 7412 // All possible cases have been handled above. Add a return to avoid the |
| 7278 // complaints from the compiler. | 7413 // complaints from the compiler. |
| 7279 UNREACHABLE(); | 7414 UNREACHABLE(); |
| 7280 return Heap::null_value(); | 7415 return isolate->heap()->null_value(); |
| 7281 } | 7416 } |
| 7282 | 7417 |
| 7283 | 7418 |
| 7284 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 7419 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
| 7285 Object* value) { | 7420 Object* value) { |
| 7286 uint32_t old_len = 0; | 7421 uint32_t old_len = 0; |
| 7287 CHECK(length()->ToArrayIndex(&old_len)); | 7422 CHECK(length()->ToArrayIndex(&old_len)); |
| 7288 // Check to see if we need to update the length. For now, we make | 7423 // Check to see if we need to update the length. For now, we make |
| 7289 // sure that the length stays within 32-bits (unsigned). | 7424 // sure that the length stays within 32-bits (unsigned). |
| 7290 if (index >= old_len && index != 0xffffffff) { | 7425 if (index >= old_len && index != 0xffffffff) { |
| 7291 Object* len; | 7426 Object* len; |
| 7292 { MaybeObject* maybe_len = | 7427 { MaybeObject* maybe_len = |
| 7293 Heap::NumberFromDouble(static_cast<double>(index) + 1); | 7428 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); |
| 7294 if (!maybe_len->ToObject(&len)) return maybe_len; | 7429 if (!maybe_len->ToObject(&len)) return maybe_len; |
| 7295 } | 7430 } |
| 7296 set_length(len); | 7431 set_length(len); |
| 7297 } | 7432 } |
| 7298 return value; | 7433 return value; |
| 7299 } | 7434 } |
| 7300 | 7435 |
| 7301 | 7436 |
| 7302 MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, | 7437 MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, |
| 7303 uint32_t index) { | 7438 uint32_t index) { |
| 7439 Heap* heap = GetHeap(); |
| 7304 // Get element works for both JSObject and JSArray since | 7440 // Get element works for both JSObject and JSArray since |
| 7305 // JSArray::length cannot change. | 7441 // JSArray::length cannot change. |
| 7306 switch (GetElementsKind()) { | 7442 switch (GetElementsKind()) { |
| 7307 case FAST_ELEMENTS: { | 7443 case FAST_ELEMENTS: { |
| 7308 FixedArray* elms = FixedArray::cast(elements()); | 7444 FixedArray* elms = FixedArray::cast(elements()); |
| 7309 if (index < static_cast<uint32_t>(elms->length())) { | 7445 if (index < static_cast<uint32_t>(elms->length())) { |
| 7310 Object* value = elms->get(index); | 7446 Object* value = elms->get(index); |
| 7311 if (!value->IsTheHole()) return value; | 7447 if (!value->IsTheHole()) return value; |
| 7312 } | 7448 } |
| 7313 break; | 7449 break; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 7342 } | 7478 } |
| 7343 break; | 7479 break; |
| 7344 } | 7480 } |
| 7345 default: | 7481 default: |
| 7346 UNREACHABLE(); | 7482 UNREACHABLE(); |
| 7347 break; | 7483 break; |
| 7348 } | 7484 } |
| 7349 | 7485 |
| 7350 // Continue searching via the prototype chain. | 7486 // Continue searching via the prototype chain. |
| 7351 Object* pt = GetPrototype(); | 7487 Object* pt = GetPrototype(); |
| 7352 if (pt == Heap::null_value()) return Heap::undefined_value(); | 7488 if (pt->IsNull()) return heap->undefined_value(); |
| 7353 return pt->GetElementWithReceiver(receiver, index); | 7489 return pt->GetElementWithReceiver(receiver, index); |
| 7354 } | 7490 } |
| 7355 | 7491 |
| 7356 | 7492 |
| 7357 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver, | 7493 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver, |
| 7358 uint32_t index) { | 7494 uint32_t index) { |
| 7495 Isolate* isolate = GetIsolate(); |
| 7359 // Make sure that the top context does not change when doing | 7496 // Make sure that the top context does not change when doing |
| 7360 // callbacks or interceptor calls. | 7497 // callbacks or interceptor calls. |
| 7361 AssertNoContextChange ncc; | 7498 AssertNoContextChange ncc; |
| 7362 HandleScope scope; | 7499 HandleScope scope(isolate); |
| 7363 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 7500 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 7364 Handle<Object> this_handle(receiver); | 7501 Handle<Object> this_handle(receiver); |
| 7365 Handle<JSObject> holder_handle(this); | 7502 Handle<JSObject> holder_handle(this); |
| 7366 | 7503 |
| 7367 if (!interceptor->getter()->IsUndefined()) { | 7504 if (!interceptor->getter()->IsUndefined()) { |
| 7368 v8::IndexedPropertyGetter getter = | 7505 v8::IndexedPropertyGetter getter = |
| 7369 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); | 7506 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); |
| 7370 LOG(ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); | 7507 LOG(isolate, |
| 7371 CustomArguments args(interceptor->data(), receiver, this); | 7508 ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); |
| 7509 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 7372 v8::AccessorInfo info(args.end()); | 7510 v8::AccessorInfo info(args.end()); |
| 7373 v8::Handle<v8::Value> result; | 7511 v8::Handle<v8::Value> result; |
| 7374 { | 7512 { |
| 7375 // Leaving JavaScript. | 7513 // Leaving JavaScript. |
| 7376 VMState state(EXTERNAL); | 7514 VMState state(isolate, EXTERNAL); |
| 7377 result = getter(index, info); | 7515 result = getter(index, info); |
| 7378 } | 7516 } |
| 7379 RETURN_IF_SCHEDULED_EXCEPTION(); | 7517 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7380 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result); | 7518 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result); |
| 7381 } | 7519 } |
| 7382 | 7520 |
| 7383 MaybeObject* raw_result = | 7521 MaybeObject* raw_result = |
| 7384 holder_handle->GetElementPostInterceptor(*this_handle, index); | 7522 holder_handle->GetElementPostInterceptor(*this_handle, index); |
| 7385 RETURN_IF_SCHEDULED_EXCEPTION(); | 7523 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7386 return raw_result; | 7524 return raw_result; |
| 7387 } | 7525 } |
| 7388 | 7526 |
| 7389 | 7527 |
| 7390 MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, | 7528 MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, |
| 7391 uint32_t index) { | 7529 uint32_t index) { |
| 7530 Heap* heap = GetHeap(); |
| 7392 // Check access rights if needed. | 7531 // Check access rights if needed. |
| 7393 if (IsAccessCheckNeeded() && | 7532 if (IsAccessCheckNeeded() && |
| 7394 !Top::MayIndexedAccess(this, index, v8::ACCESS_GET)) { | 7533 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) { |
| 7395 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET); | 7534 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); |
| 7396 return Heap::undefined_value(); | 7535 return heap->undefined_value(); |
| 7397 } | 7536 } |
| 7398 | 7537 |
| 7399 if (HasIndexedInterceptor()) { | 7538 if (HasIndexedInterceptor()) { |
| 7400 return GetElementWithInterceptor(receiver, index); | 7539 return GetElementWithInterceptor(receiver, index); |
| 7401 } | 7540 } |
| 7402 | 7541 |
| 7403 // Get element works for both JSObject and JSArray since | 7542 // Get element works for both JSObject and JSArray since |
| 7404 // JSArray::length cannot change. | 7543 // JSArray::length cannot change. |
| 7405 switch (GetElementsKind()) { | 7544 switch (GetElementsKind()) { |
| 7406 case FAST_ELEMENTS: { | 7545 case FAST_ELEMENTS: { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 7437 index, | 7576 index, |
| 7438 this); | 7577 this); |
| 7439 } | 7578 } |
| 7440 return element; | 7579 return element; |
| 7441 } | 7580 } |
| 7442 break; | 7581 break; |
| 7443 } | 7582 } |
| 7444 } | 7583 } |
| 7445 | 7584 |
| 7446 Object* pt = GetPrototype(); | 7585 Object* pt = GetPrototype(); |
| 7447 if (pt == Heap::null_value()) return Heap::undefined_value(); | 7586 if (pt == heap->null_value()) return heap->undefined_value(); |
| 7448 return pt->GetElementWithReceiver(receiver, index); | 7587 return pt->GetElementWithReceiver(receiver, index); |
| 7449 } | 7588 } |
| 7450 | 7589 |
| 7451 | 7590 |
| 7452 MaybeObject* JSObject::GetExternalElement(uint32_t index) { | 7591 MaybeObject* JSObject::GetExternalElement(uint32_t index) { |
| 7453 // Get element works for both JSObject and JSArray since | 7592 // Get element works for both JSObject and JSArray since |
| 7454 // JSArray::length cannot change. | 7593 // JSArray::length cannot change. |
| 7455 switch (GetElementsKind()) { | 7594 switch (GetElementsKind()) { |
| 7456 case EXTERNAL_PIXEL_ELEMENTS: { | 7595 case EXTERNAL_PIXEL_ELEMENTS: { |
| 7457 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 7596 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7492 if (index < static_cast<uint32_t>(array->length())) { | 7631 if (index < static_cast<uint32_t>(array->length())) { |
| 7493 uint16_t value = array->get(index); | 7632 uint16_t value = array->get(index); |
| 7494 return Smi::FromInt(value); | 7633 return Smi::FromInt(value); |
| 7495 } | 7634 } |
| 7496 break; | 7635 break; |
| 7497 } | 7636 } |
| 7498 case EXTERNAL_INT_ELEMENTS: { | 7637 case EXTERNAL_INT_ELEMENTS: { |
| 7499 ExternalIntArray* array = ExternalIntArray::cast(elements()); | 7638 ExternalIntArray* array = ExternalIntArray::cast(elements()); |
| 7500 if (index < static_cast<uint32_t>(array->length())) { | 7639 if (index < static_cast<uint32_t>(array->length())) { |
| 7501 int32_t value = array->get(index); | 7640 int32_t value = array->get(index); |
| 7502 return Heap::NumberFromInt32(value); | 7641 return GetHeap()->NumberFromInt32(value); |
| 7503 } | 7642 } |
| 7504 break; | 7643 break; |
| 7505 } | 7644 } |
| 7506 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | 7645 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 7507 ExternalUnsignedIntArray* array = | 7646 ExternalUnsignedIntArray* array = |
| 7508 ExternalUnsignedIntArray::cast(elements()); | 7647 ExternalUnsignedIntArray::cast(elements()); |
| 7509 if (index < static_cast<uint32_t>(array->length())) { | 7648 if (index < static_cast<uint32_t>(array->length())) { |
| 7510 uint32_t value = array->get(index); | 7649 uint32_t value = array->get(index); |
| 7511 return Heap::NumberFromUint32(value); | 7650 return GetHeap()->NumberFromUint32(value); |
| 7512 } | 7651 } |
| 7513 break; | 7652 break; |
| 7514 } | 7653 } |
| 7515 case EXTERNAL_FLOAT_ELEMENTS: { | 7654 case EXTERNAL_FLOAT_ELEMENTS: { |
| 7516 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); | 7655 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); |
| 7517 if (index < static_cast<uint32_t>(array->length())) { | 7656 if (index < static_cast<uint32_t>(array->length())) { |
| 7518 float value = array->get(index); | 7657 float value = array->get(index); |
| 7519 return Heap::AllocateHeapNumber(value); | 7658 return GetHeap()->AllocateHeapNumber(value); |
| 7520 } | 7659 } |
| 7521 break; | 7660 break; |
| 7522 } | 7661 } |
| 7523 case FAST_ELEMENTS: | 7662 case FAST_ELEMENTS: |
| 7524 case DICTIONARY_ELEMENTS: | 7663 case DICTIONARY_ELEMENTS: |
| 7525 UNREACHABLE(); | 7664 UNREACHABLE(); |
| 7526 break; | 7665 break; |
| 7527 } | 7666 } |
| 7528 return Heap::undefined_value(); | 7667 return GetHeap()->undefined_value(); |
| 7529 } | 7668 } |
| 7530 | 7669 |
| 7531 | 7670 |
| 7532 bool JSObject::HasDenseElements() { | 7671 bool JSObject::HasDenseElements() { |
| 7533 int capacity = 0; | 7672 int capacity = 0; |
| 7534 int number_of_elements = 0; | 7673 int number_of_elements = 0; |
| 7535 | 7674 |
| 7536 switch (GetElementsKind()) { | 7675 switch (GetElementsKind()) { |
| 7537 case FAST_ELEMENTS: { | 7676 case FAST_ELEMENTS: { |
| 7538 FixedArray* elms = FixedArray::cast(elements()); | 7677 FixedArray* elms = FixedArray::cast(elements()); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7663 Object* result = | 7802 Object* result = |
| 7664 constructor->shared()->get_api_func_data()->indexed_property_handler(); | 7803 constructor->shared()->get_api_func_data()->indexed_property_handler(); |
| 7665 return InterceptorInfo::cast(result); | 7804 return InterceptorInfo::cast(result); |
| 7666 } | 7805 } |
| 7667 | 7806 |
| 7668 | 7807 |
| 7669 MaybeObject* JSObject::GetPropertyPostInterceptor( | 7808 MaybeObject* JSObject::GetPropertyPostInterceptor( |
| 7670 JSObject* receiver, | 7809 JSObject* receiver, |
| 7671 String* name, | 7810 String* name, |
| 7672 PropertyAttributes* attributes) { | 7811 PropertyAttributes* attributes) { |
| 7812 Heap* heap = GetHeap(); |
| 7673 // Check local property in holder, ignore interceptor. | 7813 // Check local property in holder, ignore interceptor. |
| 7674 LookupResult result; | 7814 LookupResult result; |
| 7675 LocalLookupRealNamedProperty(name, &result); | 7815 LocalLookupRealNamedProperty(name, &result); |
| 7676 if (result.IsProperty()) { | 7816 if (result.IsProperty()) { |
| 7677 return GetProperty(receiver, &result, name, attributes); | 7817 return GetProperty(receiver, &result, name, attributes); |
| 7678 } | 7818 } |
| 7679 // Continue searching via the prototype chain. | 7819 // Continue searching via the prototype chain. |
| 7680 Object* pt = GetPrototype(); | 7820 Object* pt = GetPrototype(); |
| 7681 *attributes = ABSENT; | 7821 *attributes = ABSENT; |
| 7682 if (pt == Heap::null_value()) return Heap::undefined_value(); | 7822 if (pt->IsNull()) return heap->undefined_value(); |
| 7683 return pt->GetPropertyWithReceiver(receiver, name, attributes); | 7823 return pt->GetPropertyWithReceiver(receiver, name, attributes); |
| 7684 } | 7824 } |
| 7685 | 7825 |
| 7686 | 7826 |
| 7687 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( | 7827 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( |
| 7688 JSObject* receiver, | 7828 JSObject* receiver, |
| 7689 String* name, | 7829 String* name, |
| 7690 PropertyAttributes* attributes) { | 7830 PropertyAttributes* attributes) { |
| 7831 Heap* heap = GetHeap(); |
| 7691 // Check local property in holder, ignore interceptor. | 7832 // Check local property in holder, ignore interceptor. |
| 7692 LookupResult result; | 7833 LookupResult result; |
| 7693 LocalLookupRealNamedProperty(name, &result); | 7834 LocalLookupRealNamedProperty(name, &result); |
| 7694 if (result.IsProperty()) { | 7835 if (result.IsProperty()) { |
| 7695 return GetProperty(receiver, &result, name, attributes); | 7836 return GetProperty(receiver, &result, name, attributes); |
| 7696 } | 7837 } |
| 7697 return Heap::undefined_value(); | 7838 return heap->undefined_value(); |
| 7698 } | 7839 } |
| 7699 | 7840 |
| 7700 | 7841 |
| 7701 MaybeObject* JSObject::GetPropertyWithInterceptor( | 7842 MaybeObject* JSObject::GetPropertyWithInterceptor( |
| 7702 JSObject* receiver, | 7843 JSObject* receiver, |
| 7703 String* name, | 7844 String* name, |
| 7704 PropertyAttributes* attributes) { | 7845 PropertyAttributes* attributes) { |
| 7846 Isolate* isolate = GetIsolate(); |
| 7705 InterceptorInfo* interceptor = GetNamedInterceptor(); | 7847 InterceptorInfo* interceptor = GetNamedInterceptor(); |
| 7706 HandleScope scope; | 7848 HandleScope scope(isolate); |
| 7707 Handle<JSObject> receiver_handle(receiver); | 7849 Handle<JSObject> receiver_handle(receiver); |
| 7708 Handle<JSObject> holder_handle(this); | 7850 Handle<JSObject> holder_handle(this); |
| 7709 Handle<String> name_handle(name); | 7851 Handle<String> name_handle(name); |
| 7710 | 7852 |
| 7711 if (!interceptor->getter()->IsUndefined()) { | 7853 if (!interceptor->getter()->IsUndefined()) { |
| 7712 v8::NamedPropertyGetter getter = | 7854 v8::NamedPropertyGetter getter = |
| 7713 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); | 7855 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); |
| 7714 LOG(ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); | 7856 LOG(isolate, |
| 7715 CustomArguments args(interceptor->data(), receiver, this); | 7857 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); |
| 7858 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 7716 v8::AccessorInfo info(args.end()); | 7859 v8::AccessorInfo info(args.end()); |
| 7717 v8::Handle<v8::Value> result; | 7860 v8::Handle<v8::Value> result; |
| 7718 { | 7861 { |
| 7719 // Leaving JavaScript. | 7862 // Leaving JavaScript. |
| 7720 VMState state(EXTERNAL); | 7863 VMState state(isolate, EXTERNAL); |
| 7721 result = getter(v8::Utils::ToLocal(name_handle), info); | 7864 result = getter(v8::Utils::ToLocal(name_handle), info); |
| 7722 } | 7865 } |
| 7723 RETURN_IF_SCHEDULED_EXCEPTION(); | 7866 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7724 if (!result.IsEmpty()) { | 7867 if (!result.IsEmpty()) { |
| 7725 *attributes = NONE; | 7868 *attributes = NONE; |
| 7726 return *v8::Utils::OpenHandle(*result); | 7869 return *v8::Utils::OpenHandle(*result); |
| 7727 } | 7870 } |
| 7728 } | 7871 } |
| 7729 | 7872 |
| 7730 MaybeObject* result = holder_handle->GetPropertyPostInterceptor( | 7873 MaybeObject* result = holder_handle->GetPropertyPostInterceptor( |
| 7731 *receiver_handle, | 7874 *receiver_handle, |
| 7732 *name_handle, | 7875 *name_handle, |
| 7733 attributes); | 7876 attributes); |
| 7734 RETURN_IF_SCHEDULED_EXCEPTION(); | 7877 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7735 return result; | 7878 return result; |
| 7736 } | 7879 } |
| 7737 | 7880 |
| 7738 | 7881 |
| 7739 bool JSObject::HasRealNamedProperty(String* key) { | 7882 bool JSObject::HasRealNamedProperty(String* key) { |
| 7883 Heap* heap = GetHeap(); |
| 7740 // Check access rights if needed. | 7884 // Check access rights if needed. |
| 7741 if (IsAccessCheckNeeded() && | 7885 if (IsAccessCheckNeeded() && |
| 7742 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 7886 !heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 7743 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 7887 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 7744 return false; | 7888 return false; |
| 7745 } | 7889 } |
| 7746 | 7890 |
| 7747 LookupResult result; | 7891 LookupResult result; |
| 7748 LocalLookupRealNamedProperty(key, &result); | 7892 LocalLookupRealNamedProperty(key, &result); |
| 7749 return result.IsProperty() && (result.type() != INTERCEPTOR); | 7893 return result.IsProperty() && (result.type() != INTERCEPTOR); |
| 7750 } | 7894 } |
| 7751 | 7895 |
| 7752 | 7896 |
| 7753 bool JSObject::HasRealElementProperty(uint32_t index) { | 7897 bool JSObject::HasRealElementProperty(uint32_t index) { |
| 7898 Heap* heap = GetHeap(); |
| 7754 // Check access rights if needed. | 7899 // Check access rights if needed. |
| 7755 if (IsAccessCheckNeeded() && | 7900 if (IsAccessCheckNeeded() && |
| 7756 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 7901 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 7757 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 7902 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 7758 return false; | 7903 return false; |
| 7759 } | 7904 } |
| 7760 | 7905 |
| 7761 // Handle [] on String objects. | 7906 // Handle [] on String objects. |
| 7762 if (this->IsStringObjectWithCharacterAt(index)) return true; | 7907 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 7763 | 7908 |
| 7764 switch (GetElementsKind()) { | 7909 switch (GetElementsKind()) { |
| 7765 case FAST_ELEMENTS: { | 7910 case FAST_ELEMENTS: { |
| 7766 uint32_t length = IsJSArray() ? | 7911 uint32_t length = IsJSArray() ? |
| 7767 static_cast<uint32_t>( | 7912 static_cast<uint32_t>( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 7787 case DICTIONARY_ELEMENTS: { | 7932 case DICTIONARY_ELEMENTS: { |
| 7788 return element_dictionary()->FindEntry(index) | 7933 return element_dictionary()->FindEntry(index) |
| 7789 != NumberDictionary::kNotFound; | 7934 != NumberDictionary::kNotFound; |
| 7790 } | 7935 } |
| 7791 default: | 7936 default: |
| 7792 UNREACHABLE(); | 7937 UNREACHABLE(); |
| 7793 break; | 7938 break; |
| 7794 } | 7939 } |
| 7795 // All possibilities have been handled above already. | 7940 // All possibilities have been handled above already. |
| 7796 UNREACHABLE(); | 7941 UNREACHABLE(); |
| 7797 return Heap::null_value(); | 7942 return heap->null_value(); |
| 7798 } | 7943 } |
| 7799 | 7944 |
| 7800 | 7945 |
| 7801 bool JSObject::HasRealNamedCallbackProperty(String* key) { | 7946 bool JSObject::HasRealNamedCallbackProperty(String* key) { |
| 7947 Heap* heap = GetHeap(); |
| 7802 // Check access rights if needed. | 7948 // Check access rights if needed. |
| 7803 if (IsAccessCheckNeeded() && | 7949 if (IsAccessCheckNeeded() && |
| 7804 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 7950 !heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 7805 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 7951 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 7806 return false; | 7952 return false; |
| 7807 } | 7953 } |
| 7808 | 7954 |
| 7809 LookupResult result; | 7955 LookupResult result; |
| 7810 LocalLookupRealNamedProperty(key, &result); | 7956 LocalLookupRealNamedProperty(key, &result); |
| 7811 return result.IsProperty() && (result.type() == CALLBACKS); | 7957 return result.IsProperty() && (result.type() == CALLBACKS); |
| 7812 } | 7958 } |
| 7813 | 7959 |
| 7814 | 7960 |
| 7815 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { | 7961 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8058 return counter; | 8204 return counter; |
| 8059 } | 8205 } |
| 8060 | 8206 |
| 8061 | 8207 |
| 8062 int JSObject::GetEnumElementKeys(FixedArray* storage) { | 8208 int JSObject::GetEnumElementKeys(FixedArray* storage) { |
| 8063 return GetLocalElementKeys(storage, | 8209 return GetLocalElementKeys(storage, |
| 8064 static_cast<PropertyAttributes>(DONT_ENUM)); | 8210 static_cast<PropertyAttributes>(DONT_ENUM)); |
| 8065 } | 8211 } |
| 8066 | 8212 |
| 8067 | 8213 |
| 8068 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { | |
| 8069 ASSERT(other->IsNumber()); | |
| 8070 return key == static_cast<uint32_t>(other->Number()); | |
| 8071 } | |
| 8072 | |
| 8073 | |
| 8074 uint32_t NumberDictionaryShape::Hash(uint32_t key) { | |
| 8075 return ComputeIntegerHash(key); | |
| 8076 } | |
| 8077 | |
| 8078 | |
| 8079 uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) { | |
| 8080 ASSERT(other->IsNumber()); | |
| 8081 return ComputeIntegerHash(static_cast<uint32_t>(other->Number())); | |
| 8082 } | |
| 8083 | |
| 8084 | |
| 8085 MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) { | |
| 8086 return Heap::NumberFromUint32(key); | |
| 8087 } | |
| 8088 | |
| 8089 | |
| 8090 bool StringDictionaryShape::IsMatch(String* key, Object* other) { | |
| 8091 // We know that all entries in a hash table had their hash keys created. | |
| 8092 // Use that knowledge to have fast failure. | |
| 8093 if (key->Hash() != String::cast(other)->Hash()) return false; | |
| 8094 return key->Equals(String::cast(other)); | |
| 8095 } | |
| 8096 | |
| 8097 | |
| 8098 uint32_t StringDictionaryShape::Hash(String* key) { | |
| 8099 return key->Hash(); | |
| 8100 } | |
| 8101 | |
| 8102 | |
| 8103 uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) { | |
| 8104 return String::cast(other)->Hash(); | |
| 8105 } | |
| 8106 | |
| 8107 | |
| 8108 MaybeObject* StringDictionaryShape::AsObject(String* key) { | |
| 8109 return key; | |
| 8110 } | |
| 8111 | |
| 8112 | |
| 8113 // StringKey simply carries a string object as key. | 8214 // StringKey simply carries a string object as key. |
| 8114 class StringKey : public HashTableKey { | 8215 class StringKey : public HashTableKey { |
| 8115 public: | 8216 public: |
| 8116 explicit StringKey(String* string) : | 8217 explicit StringKey(String* string) : |
| 8117 string_(string), | 8218 string_(string), |
| 8118 hash_(HashForObject(string)) { } | 8219 hash_(HashForObject(string)) { } |
| 8119 | 8220 |
| 8120 bool IsMatch(Object* string) { | 8221 bool IsMatch(Object* string) { |
| 8121 // We know that all entries in a hash table had their hash keys created. | 8222 // We know that all entries in a hash table had their hash keys created. |
| 8122 // Use that knowledge to have fast failure. | 8223 // Use that knowledge to have fast failure. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8185 FixedArray* pair = FixedArray::cast(obj); | 8286 FixedArray* pair = FixedArray::cast(obj); |
| 8186 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); | 8287 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| 8187 String* source = String::cast(pair->get(1)); | 8288 String* source = String::cast(pair->get(1)); |
| 8188 StrictModeFlag strict_mode = static_cast<StrictModeFlag>( | 8289 StrictModeFlag strict_mode = static_cast<StrictModeFlag>( |
| 8189 Smi::cast(pair->get(2))->value()); | 8290 Smi::cast(pair->get(2))->value()); |
| 8190 return StringSharedHashHelper(source, shared, strict_mode); | 8291 return StringSharedHashHelper(source, shared, strict_mode); |
| 8191 } | 8292 } |
| 8192 | 8293 |
| 8193 MUST_USE_RESULT MaybeObject* AsObject() { | 8294 MUST_USE_RESULT MaybeObject* AsObject() { |
| 8194 Object* obj; | 8295 Object* obj; |
| 8195 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(3); | 8296 { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(3); |
| 8196 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8297 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8197 } | 8298 } |
| 8198 FixedArray* pair = FixedArray::cast(obj); | 8299 FixedArray* pair = FixedArray::cast(obj); |
| 8199 pair->set(0, shared_); | 8300 pair->set(0, shared_); |
| 8200 pair->set(1, source_); | 8301 pair->set(1, source_); |
| 8201 pair->set(2, Smi::FromInt(strict_mode_)); | 8302 pair->set(2, Smi::FromInt(strict_mode_)); |
| 8202 return pair; | 8303 return pair; |
| 8203 } | 8304 } |
| 8204 | 8305 |
| 8205 private: | 8306 private: |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8269 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. | 8370 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
| 8270 return result; | 8371 return result; |
| 8271 } | 8372 } |
| 8272 | 8373 |
| 8273 uint32_t HashForObject(Object* other) { | 8374 uint32_t HashForObject(Object* other) { |
| 8274 return String::cast(other)->Hash(); | 8375 return String::cast(other)->Hash(); |
| 8275 } | 8376 } |
| 8276 | 8377 |
| 8277 MaybeObject* AsObject() { | 8378 MaybeObject* AsObject() { |
| 8278 if (hash_field_ == 0) Hash(); | 8379 if (hash_field_ == 0) Hash(); |
| 8279 return Heap::AllocateSymbol(string_, chars_, hash_field_); | 8380 return Isolate::Current()->heap()->AllocateSymbol( |
| 8381 string_, chars_, hash_field_); |
| 8280 } | 8382 } |
| 8281 | 8383 |
| 8282 Vector<const char> string_; | 8384 Vector<const char> string_; |
| 8283 uint32_t hash_field_; | 8385 uint32_t hash_field_; |
| 8284 int chars_; // Caches the number of characters when computing the hash code. | 8386 int chars_; // Caches the number of characters when computing the hash code. |
| 8285 }; | 8387 }; |
| 8286 | 8388 |
| 8287 | 8389 |
| 8288 template <typename Char> | 8390 template <typename Char> |
| 8289 class SequentialSymbolKey : public HashTableKey { | 8391 class SequentialSymbolKey : public HashTableKey { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8336 public: | 8438 public: |
| 8337 explicit AsciiSymbolKey(Vector<const char> str) | 8439 explicit AsciiSymbolKey(Vector<const char> str) |
| 8338 : SequentialSymbolKey<char>(str) { } | 8440 : SequentialSymbolKey<char>(str) { } |
| 8339 | 8441 |
| 8340 bool IsMatch(Object* string) { | 8442 bool IsMatch(Object* string) { |
| 8341 return String::cast(string)->IsAsciiEqualTo(string_); | 8443 return String::cast(string)->IsAsciiEqualTo(string_); |
| 8342 } | 8444 } |
| 8343 | 8445 |
| 8344 MaybeObject* AsObject() { | 8446 MaybeObject* AsObject() { |
| 8345 if (hash_field_ == 0) Hash(); | 8447 if (hash_field_ == 0) Hash(); |
| 8346 return Heap::AllocateAsciiSymbol(string_, hash_field_); | 8448 return HEAP->AllocateAsciiSymbol(string_, hash_field_); |
| 8347 } | 8449 } |
| 8348 }; | 8450 }; |
| 8349 | 8451 |
| 8350 | 8452 |
| 8351 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> { | 8453 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> { |
| 8352 public: | 8454 public: |
| 8353 explicit TwoByteSymbolKey(Vector<const uc16> str) | 8455 explicit TwoByteSymbolKey(Vector<const uc16> str) |
| 8354 : SequentialSymbolKey<uc16>(str) { } | 8456 : SequentialSymbolKey<uc16>(str) { } |
| 8355 | 8457 |
| 8356 bool IsMatch(Object* string) { | 8458 bool IsMatch(Object* string) { |
| 8357 return String::cast(string)->IsTwoByteEqualTo(string_); | 8459 return String::cast(string)->IsTwoByteEqualTo(string_); |
| 8358 } | 8460 } |
| 8359 | 8461 |
| 8360 MaybeObject* AsObject() { | 8462 MaybeObject* AsObject() { |
| 8361 if (hash_field_ == 0) Hash(); | 8463 if (hash_field_ == 0) Hash(); |
| 8362 return Heap::AllocateTwoByteSymbol(string_, hash_field_); | 8464 return HEAP->AllocateTwoByteSymbol(string_, hash_field_); |
| 8363 } | 8465 } |
| 8364 }; | 8466 }; |
| 8365 | 8467 |
| 8366 | 8468 |
| 8367 // SymbolKey carries a string/symbol object as key. | 8469 // SymbolKey carries a string/symbol object as key. |
| 8368 class SymbolKey : public HashTableKey { | 8470 class SymbolKey : public HashTableKey { |
| 8369 public: | 8471 public: |
| 8370 explicit SymbolKey(String* string) : string_(string) { } | 8472 explicit SymbolKey(String* string) |
| 8473 : string_(string) { } |
| 8371 | 8474 |
| 8372 bool IsMatch(Object* string) { | 8475 bool IsMatch(Object* string) { |
| 8373 return String::cast(string)->Equals(string_); | 8476 return String::cast(string)->Equals(string_); |
| 8374 } | 8477 } |
| 8375 | 8478 |
| 8376 uint32_t Hash() { return string_->Hash(); } | 8479 uint32_t Hash() { return string_->Hash(); } |
| 8377 | 8480 |
| 8378 uint32_t HashForObject(Object* other) { | 8481 uint32_t HashForObject(Object* other) { |
| 8379 return String::cast(other)->Hash(); | 8482 return String::cast(other)->Hash(); |
| 8380 } | 8483 } |
| 8381 | 8484 |
| 8382 MaybeObject* AsObject() { | 8485 MaybeObject* AsObject() { |
| 8383 // Attempt to flatten the string, so that symbols will most often | 8486 // Attempt to flatten the string, so that symbols will most often |
| 8384 // be flat strings. | 8487 // be flat strings. |
| 8385 string_ = string_->TryFlattenGetString(); | 8488 string_ = string_->TryFlattenGetString(); |
| 8489 Heap* heap = string_->GetHeap(); |
| 8386 // Transform string to symbol if possible. | 8490 // Transform string to symbol if possible. |
| 8387 Map* map = Heap::SymbolMapForString(string_); | 8491 Map* map = heap->SymbolMapForString(string_); |
| 8388 if (map != NULL) { | 8492 if (map != NULL) { |
| 8389 string_->set_map(map); | 8493 string_->set_map(map); |
| 8390 ASSERT(string_->IsSymbol()); | 8494 ASSERT(string_->IsSymbol()); |
| 8391 return string_; | 8495 return string_; |
| 8392 } | 8496 } |
| 8393 // Otherwise allocate a new symbol. | 8497 // Otherwise allocate a new symbol. |
| 8394 StringInputBuffer buffer(string_); | 8498 StringInputBuffer buffer(string_); |
| 8395 return Heap::AllocateInternalSymbol(&buffer, | 8499 return heap->AllocateInternalSymbol(&buffer, |
| 8396 string_->length(), | 8500 string_->length(), |
| 8397 string_->hash_field()); | 8501 string_->hash_field()); |
| 8398 } | 8502 } |
| 8399 | 8503 |
| 8400 static uint32_t StringHash(Object* obj) { | 8504 static uint32_t StringHash(Object* obj) { |
| 8401 return String::cast(obj)->Hash(); | 8505 return String::cast(obj)->Hash(); |
| 8402 } | 8506 } |
| 8403 | 8507 |
| 8404 String* string_; | 8508 String* string_; |
| 8405 }; | 8509 }; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 8424 PretenureFlag pretenure) { | 8528 PretenureFlag pretenure) { |
| 8425 const int kMinCapacity = 32; | 8529 const int kMinCapacity = 32; |
| 8426 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); | 8530 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); |
| 8427 if (capacity < kMinCapacity) { | 8531 if (capacity < kMinCapacity) { |
| 8428 capacity = kMinCapacity; // Guarantee min capacity. | 8532 capacity = kMinCapacity; // Guarantee min capacity. |
| 8429 } else if (capacity > HashTable::kMaxCapacity) { | 8533 } else if (capacity > HashTable::kMaxCapacity) { |
| 8430 return Failure::OutOfMemoryException(); | 8534 return Failure::OutOfMemoryException(); |
| 8431 } | 8535 } |
| 8432 | 8536 |
| 8433 Object* obj; | 8537 Object* obj; |
| 8434 { MaybeObject* maybe_obj = | 8538 { MaybeObject* maybe_obj = Isolate::Current()->heap()-> |
| 8435 Heap::AllocateHashTable(EntryToIndex(capacity), pretenure); | 8539 AllocateHashTable(EntryToIndex(capacity), pretenure); |
| 8436 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8540 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8437 } | 8541 } |
| 8438 HashTable::cast(obj)->SetNumberOfElements(0); | 8542 HashTable::cast(obj)->SetNumberOfElements(0); |
| 8439 HashTable::cast(obj)->SetNumberOfDeletedElements(0); | 8543 HashTable::cast(obj)->SetNumberOfDeletedElements(0); |
| 8440 HashTable::cast(obj)->SetCapacity(capacity); | 8544 HashTable::cast(obj)->SetCapacity(capacity); |
| 8441 return obj; | 8545 return obj; |
| 8442 } | 8546 } |
| 8443 | 8547 |
| 8444 | 8548 |
| 8445 // Find entry for key otherwise return kNotFound. | 8549 // Find entry for key otherwise return kNotFound. |
| 8446 template<typename Shape, typename Key> | |
| 8447 int HashTable<Shape, Key>::FindEntry(Key key) { | |
| 8448 uint32_t capacity = Capacity(); | |
| 8449 uint32_t entry = FirstProbe(Shape::Hash(key), capacity); | |
| 8450 uint32_t count = 1; | |
| 8451 // EnsureCapacity will guarantee the hash table is never full. | |
| 8452 while (true) { | |
| 8453 Object* element = KeyAt(entry); | |
| 8454 if (element->IsUndefined()) break; // Empty entry. | |
| 8455 if (!element->IsNull() && Shape::IsMatch(key, element)) return entry; | |
| 8456 entry = NextProbe(entry, count++, capacity); | |
| 8457 } | |
| 8458 return kNotFound; | |
| 8459 } | |
| 8460 | |
| 8461 | |
| 8462 // Find entry for key otherwise return kNotFound. | |
| 8463 int StringDictionary::FindEntry(String* key) { | 8550 int StringDictionary::FindEntry(String* key) { |
| 8464 if (!key->IsSymbol()) { | 8551 if (!key->IsSymbol()) { |
| 8465 return HashTable<StringDictionaryShape, String*>::FindEntry(key); | 8552 return HashTable<StringDictionaryShape, String*>::FindEntry(key); |
| 8466 } | 8553 } |
| 8467 | 8554 |
| 8468 // Optimized for symbol key. Knowledge of the key type allows: | 8555 // Optimized for symbol key. Knowledge of the key type allows: |
| 8469 // 1. Move the check if the key is a symbol out of the loop. | 8556 // 1. Move the check if the key is a symbol out of the loop. |
| 8470 // 2. Avoid comparing hash codes in symbol to symbol comparision. | 8557 // 2. Avoid comparing hash codes in symbol to symbol comparision. |
| 8471 // 3. Detect a case when a dictionary key is not a symbol but the key is. | 8558 // 3. Detect a case when a dictionary key is not a symbol but the key is. |
| 8472 // In case of positive result the dictionary key may be replaced by | 8559 // In case of positive result the dictionary key may be replaced by |
| (...skipping 21 matching lines...) Expand all Loading... |
| 8494 } | 8581 } |
| 8495 ASSERT(element->IsNull() || !String::cast(element)->Equals(key)); | 8582 ASSERT(element->IsNull() || !String::cast(element)->Equals(key)); |
| 8496 entry = NextProbe(entry, count++, capacity); | 8583 entry = NextProbe(entry, count++, capacity); |
| 8497 } | 8584 } |
| 8498 return kNotFound; | 8585 return kNotFound; |
| 8499 } | 8586 } |
| 8500 | 8587 |
| 8501 | 8588 |
| 8502 template<typename Shape, typename Key> | 8589 template<typename Shape, typename Key> |
| 8503 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { | 8590 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { |
| 8591 Heap* heap = GetHeap(); |
| 8504 int capacity = Capacity(); | 8592 int capacity = Capacity(); |
| 8505 int nof = NumberOfElements() + n; | 8593 int nof = NumberOfElements() + n; |
| 8506 int nod = NumberOfDeletedElements(); | 8594 int nod = NumberOfDeletedElements(); |
| 8507 // Return if: | 8595 // Return if: |
| 8508 // 50% is still free after adding n elements and | 8596 // 50% is still free after adding n elements and |
| 8509 // at most 50% of the free elements are deleted elements. | 8597 // at most 50% of the free elements are deleted elements. |
| 8510 if (nod <= (capacity - nof) >> 1) { | 8598 if (nod <= (capacity - nof) >> 1) { |
| 8511 int needed_free = nof >> 1; | 8599 int needed_free = nof >> 1; |
| 8512 if (nof + needed_free <= capacity) return this; | 8600 if (nof + needed_free <= capacity) return this; |
| 8513 } | 8601 } |
| 8514 | 8602 |
| 8515 const int kMinCapacityForPretenure = 256; | 8603 const int kMinCapacityForPretenure = 256; |
| 8516 bool pretenure = | 8604 bool pretenure = |
| 8517 (capacity > kMinCapacityForPretenure) && !Heap::InNewSpace(this); | 8605 (capacity > kMinCapacityForPretenure) && !heap->InNewSpace(this); |
| 8518 Object* obj; | 8606 Object* obj; |
| 8519 { MaybeObject* maybe_obj = | 8607 { MaybeObject* maybe_obj = |
| 8520 Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); | 8608 Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); |
| 8521 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8609 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8522 } | 8610 } |
| 8523 | 8611 |
| 8524 AssertNoAllocation no_gc; | 8612 AssertNoAllocation no_gc; |
| 8525 HashTable* table = HashTable::cast(obj); | 8613 HashTable* table = HashTable::cast(obj); |
| 8526 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc); | 8614 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc); |
| 8527 | 8615 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8639 template | 8727 template |
| 8640 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); | 8728 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); |
| 8641 | 8729 |
| 8642 template | 8730 template |
| 8643 int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t); | 8731 int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t); |
| 8644 | 8732 |
| 8645 | 8733 |
| 8646 // Collates undefined and unexisting elements below limit from position | 8734 // Collates undefined and unexisting elements below limit from position |
| 8647 // zero of the elements. The object stays in Dictionary mode. | 8735 // zero of the elements. The object stays in Dictionary mode. |
| 8648 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { | 8736 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { |
| 8737 Heap* heap = GetHeap(); |
| 8649 ASSERT(HasDictionaryElements()); | 8738 ASSERT(HasDictionaryElements()); |
| 8650 // Must stay in dictionary mode, either because of requires_slow_elements, | 8739 // Must stay in dictionary mode, either because of requires_slow_elements, |
| 8651 // or because we are not going to sort (and therefore compact) all of the | 8740 // or because we are not going to sort (and therefore compact) all of the |
| 8652 // elements. | 8741 // elements. |
| 8653 NumberDictionary* dict = element_dictionary(); | 8742 NumberDictionary* dict = element_dictionary(); |
| 8654 HeapNumber* result_double = NULL; | 8743 HeapNumber* result_double = NULL; |
| 8655 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 8744 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8656 // Allocate space for result before we start mutating the object. | 8745 // Allocate space for result before we start mutating the object. |
| 8657 Object* new_double; | 8746 Object* new_double; |
| 8658 { MaybeObject* maybe_new_double = Heap::AllocateHeapNumber(0.0); | 8747 { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0); |
| 8659 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; | 8748 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; |
| 8660 } | 8749 } |
| 8661 result_double = HeapNumber::cast(new_double); | 8750 result_double = HeapNumber::cast(new_double); |
| 8662 } | 8751 } |
| 8663 | 8752 |
| 8664 Object* obj; | 8753 Object* obj; |
| 8665 { MaybeObject* maybe_obj = | 8754 { MaybeObject* maybe_obj = |
| 8666 NumberDictionary::Allocate(dict->NumberOfElements()); | 8755 NumberDictionary::Allocate(dict->NumberOfElements()); |
| 8667 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8756 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8668 } | 8757 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8714 } | 8803 } |
| 8715 | 8804 |
| 8716 uint32_t result = pos; | 8805 uint32_t result = pos; |
| 8717 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); | 8806 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); |
| 8718 while (undefs > 0) { | 8807 while (undefs > 0) { |
| 8719 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 8808 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8720 // Adding an entry with the key beyond smi-range requires | 8809 // Adding an entry with the key beyond smi-range requires |
| 8721 // allocation. Bailout. | 8810 // allocation. Bailout. |
| 8722 return Smi::FromInt(-1); | 8811 return Smi::FromInt(-1); |
| 8723 } | 8812 } |
| 8724 new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details)-> | 8813 new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)-> |
| 8725 ToObjectUnchecked(); | 8814 ToObjectUnchecked(); |
| 8726 pos++; | 8815 pos++; |
| 8727 undefs--; | 8816 undefs--; |
| 8728 } | 8817 } |
| 8729 | 8818 |
| 8730 set_elements(new_dict); | 8819 set_elements(new_dict); |
| 8731 | 8820 |
| 8732 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { | 8821 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8733 return Smi::FromInt(static_cast<int>(result)); | 8822 return Smi::FromInt(static_cast<int>(result)); |
| 8734 } | 8823 } |
| 8735 | 8824 |
| 8736 ASSERT_NE(NULL, result_double); | 8825 ASSERT_NE(NULL, result_double); |
| 8737 result_double->set_value(static_cast<double>(result)); | 8826 result_double->set_value(static_cast<double>(result)); |
| 8738 return result_double; | 8827 return result_double; |
| 8739 } | 8828 } |
| 8740 | 8829 |
| 8741 | 8830 |
| 8742 // Collects all defined (non-hole) and non-undefined (array) elements at | 8831 // Collects all defined (non-hole) and non-undefined (array) elements at |
| 8743 // the start of the elements array. | 8832 // the start of the elements array. |
| 8744 // If the object is in dictionary mode, it is converted to fast elements | 8833 // If the object is in dictionary mode, it is converted to fast elements |
| 8745 // mode. | 8834 // mode. |
| 8746 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { | 8835 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { |
| 8836 Heap* heap = GetHeap(); |
| 8747 ASSERT(!HasExternalArrayElements()); | 8837 ASSERT(!HasExternalArrayElements()); |
| 8748 | 8838 |
| 8749 if (HasDictionaryElements()) { | 8839 if (HasDictionaryElements()) { |
| 8750 // Convert to fast elements containing only the existing properties. | 8840 // Convert to fast elements containing only the existing properties. |
| 8751 // Ordering is irrelevant, since we are going to sort anyway. | 8841 // Ordering is irrelevant, since we are going to sort anyway. |
| 8752 NumberDictionary* dict = element_dictionary(); | 8842 NumberDictionary* dict = element_dictionary(); |
| 8753 if (IsJSArray() || dict->requires_slow_elements() || | 8843 if (IsJSArray() || dict->requires_slow_elements() || |
| 8754 dict->max_number_key() >= limit) { | 8844 dict->max_number_key() >= limit) { |
| 8755 return PrepareSlowElementsForSort(limit); | 8845 return PrepareSlowElementsForSort(limit); |
| 8756 } | 8846 } |
| 8757 // Convert to fast elements. | 8847 // Convert to fast elements. |
| 8758 | 8848 |
| 8759 Object* obj; | 8849 Object* obj; |
| 8760 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); | 8850 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); |
| 8761 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8851 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8762 } | 8852 } |
| 8763 Map* new_map = Map::cast(obj); | 8853 Map* new_map = Map::cast(obj); |
| 8764 | 8854 |
| 8765 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED; | 8855 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; |
| 8766 Object* new_array; | 8856 Object* new_array; |
| 8767 { MaybeObject* maybe_new_array = | 8857 { MaybeObject* maybe_new_array = |
| 8768 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); | 8858 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); |
| 8769 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 8859 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; |
| 8770 } | 8860 } |
| 8771 FixedArray* fast_elements = FixedArray::cast(new_array); | 8861 FixedArray* fast_elements = FixedArray::cast(new_array); |
| 8772 dict->CopyValuesTo(fast_elements); | 8862 dict->CopyValuesTo(fast_elements); |
| 8773 | 8863 |
| 8774 set_map(new_map); | 8864 set_map(new_map); |
| 8775 set_elements(fast_elements); | 8865 set_elements(fast_elements); |
| 8776 } else { | 8866 } else { |
| 8777 Object* obj; | 8867 Object* obj; |
| 8778 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 8868 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 8791 } | 8881 } |
| 8792 if (limit == 0) { | 8882 if (limit == 0) { |
| 8793 return Smi::FromInt(0); | 8883 return Smi::FromInt(0); |
| 8794 } | 8884 } |
| 8795 | 8885 |
| 8796 HeapNumber* result_double = NULL; | 8886 HeapNumber* result_double = NULL; |
| 8797 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 8887 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8798 // Pessimistically allocate space for return value before | 8888 // Pessimistically allocate space for return value before |
| 8799 // we start mutating the array. | 8889 // we start mutating the array. |
| 8800 Object* new_double; | 8890 Object* new_double; |
| 8801 { MaybeObject* maybe_new_double = Heap::AllocateHeapNumber(0.0); | 8891 { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0); |
| 8802 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; | 8892 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; |
| 8803 } | 8893 } |
| 8804 result_double = HeapNumber::cast(new_double); | 8894 result_double = HeapNumber::cast(new_double); |
| 8805 } | 8895 } |
| 8806 | 8896 |
| 8807 AssertNoAllocation no_alloc; | 8897 AssertNoAllocation no_alloc; |
| 8808 | 8898 |
| 8809 // Split elements into defined, undefined and the_hole, in that order. | 8899 // Split elements into defined, undefined and the_hole, in that order. |
| 8810 // Only count locations for undefined and the hole, and fill them afterwards. | 8900 // Only count locations for undefined and the hole, and fill them afterwards. |
| 8811 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc); | 8901 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8885 // converted to a number type further up in the call chain. | 8975 // converted to a number type further up in the call chain. |
| 8886 ASSERT(value->IsUndefined()); | 8976 ASSERT(value->IsUndefined()); |
| 8887 } | 8977 } |
| 8888 set(index, clamped_value); | 8978 set(index, clamped_value); |
| 8889 } | 8979 } |
| 8890 return Smi::FromInt(clamped_value); | 8980 return Smi::FromInt(clamped_value); |
| 8891 } | 8981 } |
| 8892 | 8982 |
| 8893 | 8983 |
| 8894 template<typename ExternalArrayClass, typename ValueType> | 8984 template<typename ExternalArrayClass, typename ValueType> |
| 8895 static MaybeObject* ExternalArrayIntSetter(ExternalArrayClass* receiver, | 8985 static MaybeObject* ExternalArrayIntSetter(Heap* heap, |
| 8986 ExternalArrayClass* receiver, |
| 8896 uint32_t index, | 8987 uint32_t index, |
| 8897 Object* value) { | 8988 Object* value) { |
| 8898 ValueType cast_value = 0; | 8989 ValueType cast_value = 0; |
| 8899 if (index < static_cast<uint32_t>(receiver->length())) { | 8990 if (index < static_cast<uint32_t>(receiver->length())) { |
| 8900 if (value->IsSmi()) { | 8991 if (value->IsSmi()) { |
| 8901 int int_value = Smi::cast(value)->value(); | 8992 int int_value = Smi::cast(value)->value(); |
| 8902 cast_value = static_cast<ValueType>(int_value); | 8993 cast_value = static_cast<ValueType>(int_value); |
| 8903 } else if (value->IsHeapNumber()) { | 8994 } else if (value->IsHeapNumber()) { |
| 8904 double double_value = HeapNumber::cast(value)->value(); | 8995 double double_value = HeapNumber::cast(value)->value(); |
| 8905 cast_value = static_cast<ValueType>(DoubleToInt32(double_value)); | 8996 cast_value = static_cast<ValueType>(DoubleToInt32(double_value)); |
| 8906 } else { | 8997 } else { |
| 8907 // Clamp undefined to zero (default). All other types have been | 8998 // Clamp undefined to zero (default). All other types have been |
| 8908 // converted to a number type further up in the call chain. | 8999 // converted to a number type further up in the call chain. |
| 8909 ASSERT(value->IsUndefined()); | 9000 ASSERT(value->IsUndefined()); |
| 8910 } | 9001 } |
| 8911 receiver->set(index, cast_value); | 9002 receiver->set(index, cast_value); |
| 8912 } | 9003 } |
| 8913 return Heap::NumberFromInt32(cast_value); | 9004 return heap->NumberFromInt32(cast_value); |
| 8914 } | 9005 } |
| 8915 | 9006 |
| 8916 | 9007 |
| 8917 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) { | 9008 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) { |
| 8918 return ExternalArrayIntSetter<ExternalByteArray, int8_t> | 9009 return ExternalArrayIntSetter<ExternalByteArray, int8_t> |
| 8919 (this, index, value); | 9010 (GetHeap(), this, index, value); |
| 8920 } | 9011 } |
| 8921 | 9012 |
| 8922 | 9013 |
| 8923 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index, | 9014 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index, |
| 8924 Object* value) { | 9015 Object* value) { |
| 8925 return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t> | 9016 return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t> |
| 8926 (this, index, value); | 9017 (GetHeap(), this, index, value); |
| 8927 } | 9018 } |
| 8928 | 9019 |
| 8929 | 9020 |
| 8930 MaybeObject* ExternalShortArray::SetValue(uint32_t index, | 9021 MaybeObject* ExternalShortArray::SetValue(uint32_t index, |
| 8931 Object* value) { | 9022 Object* value) { |
| 8932 return ExternalArrayIntSetter<ExternalShortArray, int16_t> | 9023 return ExternalArrayIntSetter<ExternalShortArray, int16_t> |
| 8933 (this, index, value); | 9024 (GetHeap(), this, index, value); |
| 8934 } | 9025 } |
| 8935 | 9026 |
| 8936 | 9027 |
| 8937 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index, | 9028 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index, |
| 8938 Object* value) { | 9029 Object* value) { |
| 8939 return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t> | 9030 return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t> |
| 8940 (this, index, value); | 9031 (GetHeap(), this, index, value); |
| 8941 } | 9032 } |
| 8942 | 9033 |
| 8943 | 9034 |
| 8944 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) { | 9035 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) { |
| 8945 return ExternalArrayIntSetter<ExternalIntArray, int32_t> | 9036 return ExternalArrayIntSetter<ExternalIntArray, int32_t> |
| 8946 (this, index, value); | 9037 (GetHeap(), this, index, value); |
| 8947 } | 9038 } |
| 8948 | 9039 |
| 8949 | 9040 |
| 8950 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { | 9041 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { |
| 8951 uint32_t cast_value = 0; | 9042 uint32_t cast_value = 0; |
| 9043 Heap* heap = GetHeap(); |
| 8952 if (index < static_cast<uint32_t>(length())) { | 9044 if (index < static_cast<uint32_t>(length())) { |
| 8953 if (value->IsSmi()) { | 9045 if (value->IsSmi()) { |
| 8954 int int_value = Smi::cast(value)->value(); | 9046 int int_value = Smi::cast(value)->value(); |
| 8955 cast_value = static_cast<uint32_t>(int_value); | 9047 cast_value = static_cast<uint32_t>(int_value); |
| 8956 } else if (value->IsHeapNumber()) { | 9048 } else if (value->IsHeapNumber()) { |
| 8957 double double_value = HeapNumber::cast(value)->value(); | 9049 double double_value = HeapNumber::cast(value)->value(); |
| 8958 cast_value = static_cast<uint32_t>(DoubleToUint32(double_value)); | 9050 cast_value = static_cast<uint32_t>(DoubleToUint32(double_value)); |
| 8959 } else { | 9051 } else { |
| 8960 // Clamp undefined to zero (default). All other types have been | 9052 // Clamp undefined to zero (default). All other types have been |
| 8961 // converted to a number type further up in the call chain. | 9053 // converted to a number type further up in the call chain. |
| 8962 ASSERT(value->IsUndefined()); | 9054 ASSERT(value->IsUndefined()); |
| 8963 } | 9055 } |
| 8964 set(index, cast_value); | 9056 set(index, cast_value); |
| 8965 } | 9057 } |
| 8966 return Heap::NumberFromUint32(cast_value); | 9058 return heap->NumberFromUint32(cast_value); |
| 8967 } | 9059 } |
| 8968 | 9060 |
| 8969 | 9061 |
| 8970 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) { | 9062 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) { |
| 8971 float cast_value = 0; | 9063 float cast_value = 0; |
| 9064 Heap* heap = GetHeap(); |
| 8972 if (index < static_cast<uint32_t>(length())) { | 9065 if (index < static_cast<uint32_t>(length())) { |
| 8973 if (value->IsSmi()) { | 9066 if (value->IsSmi()) { |
| 8974 int int_value = Smi::cast(value)->value(); | 9067 int int_value = Smi::cast(value)->value(); |
| 8975 cast_value = static_cast<float>(int_value); | 9068 cast_value = static_cast<float>(int_value); |
| 8976 } else if (value->IsHeapNumber()) { | 9069 } else if (value->IsHeapNumber()) { |
| 8977 double double_value = HeapNumber::cast(value)->value(); | 9070 double double_value = HeapNumber::cast(value)->value(); |
| 8978 cast_value = static_cast<float>(double_value); | 9071 cast_value = static_cast<float>(double_value); |
| 8979 } else { | 9072 } else { |
| 8980 // Clamp undefined to zero (default). All other types have been | 9073 // Clamp undefined to zero (default). All other types have been |
| 8981 // converted to a number type further up in the call chain. | 9074 // converted to a number type further up in the call chain. |
| 8982 ASSERT(value->IsUndefined()); | 9075 ASSERT(value->IsUndefined()); |
| 8983 } | 9076 } |
| 8984 set(index, cast_value); | 9077 set(index, cast_value); |
| 8985 } | 9078 } |
| 8986 return Heap::AllocateHeapNumber(cast_value); | 9079 return heap->AllocateHeapNumber(cast_value); |
| 8987 } | 9080 } |
| 8988 | 9081 |
| 8989 | 9082 |
| 8990 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { | 9083 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
| 8991 ASSERT(!HasFastProperties()); | 9084 ASSERT(!HasFastProperties()); |
| 8992 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 9085 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 8993 return JSGlobalPropertyCell::cast(value); | 9086 return JSGlobalPropertyCell::cast(value); |
| 8994 } | 9087 } |
| 8995 | 9088 |
| 8996 | 9089 |
| 8997 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { | 9090 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { |
| 8998 ASSERT(!HasFastProperties()); | 9091 ASSERT(!HasFastProperties()); |
| 9092 Heap* heap = GetHeap(); |
| 8999 int entry = property_dictionary()->FindEntry(name); | 9093 int entry = property_dictionary()->FindEntry(name); |
| 9000 if (entry == StringDictionary::kNotFound) { | 9094 if (entry == StringDictionary::kNotFound) { |
| 9001 Object* cell; | 9095 Object* cell; |
| 9002 { MaybeObject* maybe_cell = | 9096 { MaybeObject* maybe_cell = |
| 9003 Heap::AllocateJSGlobalPropertyCell(Heap::the_hole_value()); | 9097 heap->AllocateJSGlobalPropertyCell(heap->the_hole_value()); |
| 9004 if (!maybe_cell->ToObject(&cell)) return maybe_cell; | 9098 if (!maybe_cell->ToObject(&cell)) return maybe_cell; |
| 9005 } | 9099 } |
| 9006 PropertyDetails details(NONE, NORMAL); | 9100 PropertyDetails details(NONE, NORMAL); |
| 9007 details = details.AsDeleted(); | 9101 details = details.AsDeleted(); |
| 9008 Object* dictionary; | 9102 Object* dictionary; |
| 9009 { MaybeObject* maybe_dictionary = | 9103 { MaybeObject* maybe_dictionary = |
| 9010 property_dictionary()->Add(name, cell, details); | 9104 property_dictionary()->Add(name, cell, details); |
| 9011 if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary; | 9105 if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary; |
| 9012 } | 9106 } |
| 9013 set_properties(StringDictionary::cast(dictionary)); | 9107 set_properties(StringDictionary::cast(dictionary)); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9165 // Add the new symbol and return it along with the symbol table. | 9259 // Add the new symbol and return it along with the symbol table. |
| 9166 entry = table->FindInsertionEntry(key->Hash()); | 9260 entry = table->FindInsertionEntry(key->Hash()); |
| 9167 table->set(EntryToIndex(entry), symbol); | 9261 table->set(EntryToIndex(entry), symbol); |
| 9168 table->ElementAdded(); | 9262 table->ElementAdded(); |
| 9169 *s = symbol; | 9263 *s = symbol; |
| 9170 return table; | 9264 return table; |
| 9171 } | 9265 } |
| 9172 | 9266 |
| 9173 | 9267 |
| 9174 Object* CompilationCacheTable::Lookup(String* src) { | 9268 Object* CompilationCacheTable::Lookup(String* src) { |
| 9269 Heap* heap = GetHeap(); |
| 9175 StringKey key(src); | 9270 StringKey key(src); |
| 9176 int entry = FindEntry(&key); | 9271 int entry = FindEntry(&key); |
| 9177 if (entry == kNotFound) return Heap::undefined_value(); | 9272 if (entry == kNotFound) return heap->undefined_value(); |
| 9178 return get(EntryToIndex(entry) + 1); | 9273 return get(EntryToIndex(entry) + 1); |
| 9179 } | 9274 } |
| 9180 | 9275 |
| 9181 | 9276 |
| 9182 Object* CompilationCacheTable::LookupEval(String* src, | 9277 Object* CompilationCacheTable::LookupEval(String* src, |
| 9183 Context* context, | 9278 Context* context, |
| 9184 StrictModeFlag strict_mode) { | 9279 StrictModeFlag strict_mode) { |
| 9185 StringSharedKey key(src, context->closure()->shared(), strict_mode); | 9280 StringSharedKey key(src, context->closure()->shared(), strict_mode); |
| 9186 int entry = FindEntry(&key); | 9281 int entry = FindEntry(&key); |
| 9187 if (entry == kNotFound) return Heap::undefined_value(); | 9282 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 9188 return get(EntryToIndex(entry) + 1); | 9283 return get(EntryToIndex(entry) + 1); |
| 9189 } | 9284 } |
| 9190 | 9285 |
| 9191 | 9286 |
| 9192 Object* CompilationCacheTable::LookupRegExp(String* src, | 9287 Object* CompilationCacheTable::LookupRegExp(String* src, |
| 9193 JSRegExp::Flags flags) { | 9288 JSRegExp::Flags flags) { |
| 9289 Heap* heap = GetHeap(); |
| 9194 RegExpKey key(src, flags); | 9290 RegExpKey key(src, flags); |
| 9195 int entry = FindEntry(&key); | 9291 int entry = FindEntry(&key); |
| 9196 if (entry == kNotFound) return Heap::undefined_value(); | 9292 if (entry == kNotFound) return heap->undefined_value(); |
| 9197 return get(EntryToIndex(entry) + 1); | 9293 return get(EntryToIndex(entry) + 1); |
| 9198 } | 9294 } |
| 9199 | 9295 |
| 9200 | 9296 |
| 9201 MaybeObject* CompilationCacheTable::Put(String* src, Object* value) { | 9297 MaybeObject* CompilationCacheTable::Put(String* src, Object* value) { |
| 9202 StringKey key(src); | 9298 StringKey key(src); |
| 9203 Object* obj; | 9299 Object* obj; |
| 9204 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 9300 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 9205 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9301 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9206 } | 9302 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9257 // We store the value in the key slot, and compare the search key | 9353 // We store the value in the key slot, and compare the search key |
| 9258 // to the stored value with a custon IsMatch function during lookups. | 9354 // to the stored value with a custon IsMatch function during lookups. |
| 9259 cache->set(EntryToIndex(entry), value); | 9355 cache->set(EntryToIndex(entry), value); |
| 9260 cache->set(EntryToIndex(entry) + 1, value); | 9356 cache->set(EntryToIndex(entry) + 1, value); |
| 9261 cache->ElementAdded(); | 9357 cache->ElementAdded(); |
| 9262 return cache; | 9358 return cache; |
| 9263 } | 9359 } |
| 9264 | 9360 |
| 9265 | 9361 |
| 9266 void CompilationCacheTable::Remove(Object* value) { | 9362 void CompilationCacheTable::Remove(Object* value) { |
| 9363 Object* null_value = GetHeap()->null_value(); |
| 9267 for (int entry = 0, size = Capacity(); entry < size; entry++) { | 9364 for (int entry = 0, size = Capacity(); entry < size; entry++) { |
| 9268 int entry_index = EntryToIndex(entry); | 9365 int entry_index = EntryToIndex(entry); |
| 9269 int value_index = entry_index + 1; | 9366 int value_index = entry_index + 1; |
| 9270 if (get(value_index) == value) { | 9367 if (get(value_index) == value) { |
| 9271 fast_set(this, entry_index, Heap::null_value()); | 9368 fast_set(this, entry_index, null_value); |
| 9272 fast_set(this, value_index, Heap::null_value()); | 9369 fast_set(this, value_index, null_value); |
| 9273 ElementRemoved(); | 9370 ElementRemoved(); |
| 9274 } | 9371 } |
| 9275 } | 9372 } |
| 9276 return; | 9373 return; |
| 9277 } | 9374 } |
| 9278 | 9375 |
| 9279 | 9376 |
| 9280 // SymbolsKey used for HashTable where key is array of symbols. | 9377 // SymbolsKey used for HashTable where key is array of symbols. |
| 9281 class SymbolsKey : public HashTableKey { | 9378 class SymbolsKey : public HashTableKey { |
| 9282 public: | 9379 public: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 9305 } | 9402 } |
| 9306 | 9403 |
| 9307 Object* AsObject() { return symbols_; } | 9404 Object* AsObject() { return symbols_; } |
| 9308 | 9405 |
| 9309 private: | 9406 private: |
| 9310 FixedArray* symbols_; | 9407 FixedArray* symbols_; |
| 9311 }; | 9408 }; |
| 9312 | 9409 |
| 9313 | 9410 |
| 9314 Object* MapCache::Lookup(FixedArray* array) { | 9411 Object* MapCache::Lookup(FixedArray* array) { |
| 9412 Heap* heap = GetHeap(); |
| 9315 SymbolsKey key(array); | 9413 SymbolsKey key(array); |
| 9316 int entry = FindEntry(&key); | 9414 int entry = FindEntry(&key); |
| 9317 if (entry == kNotFound) return Heap::undefined_value(); | 9415 if (entry == kNotFound) return heap->undefined_value(); |
| 9318 return get(EntryToIndex(entry) + 1); | 9416 return get(EntryToIndex(entry) + 1); |
| 9319 } | 9417 } |
| 9320 | 9418 |
| 9321 | 9419 |
| 9322 MaybeObject* MapCache::Put(FixedArray* array, Map* value) { | 9420 MaybeObject* MapCache::Put(FixedArray* array, Map* value) { |
| 9323 SymbolsKey key(array); | 9421 SymbolsKey key(array); |
| 9324 Object* obj; | 9422 Object* obj; |
| 9325 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 9423 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 9326 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9424 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9327 } | 9425 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 9344 } | 9442 } |
| 9345 // Initialize the next enumeration index. | 9443 // Initialize the next enumeration index. |
| 9346 Dictionary<Shape, Key>::cast(obj)-> | 9444 Dictionary<Shape, Key>::cast(obj)-> |
| 9347 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); | 9445 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
| 9348 return obj; | 9446 return obj; |
| 9349 } | 9447 } |
| 9350 | 9448 |
| 9351 | 9449 |
| 9352 template<typename Shape, typename Key> | 9450 template<typename Shape, typename Key> |
| 9353 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { | 9451 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { |
| 9452 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
| 9354 int length = HashTable<Shape, Key>::NumberOfElements(); | 9453 int length = HashTable<Shape, Key>::NumberOfElements(); |
| 9355 | 9454 |
| 9356 // Allocate and initialize iteration order array. | 9455 // Allocate and initialize iteration order array. |
| 9357 Object* obj; | 9456 Object* obj; |
| 9358 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(length); | 9457 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length); |
| 9359 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9458 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9360 } | 9459 } |
| 9361 FixedArray* iteration_order = FixedArray::cast(obj); | 9460 FixedArray* iteration_order = FixedArray::cast(obj); |
| 9362 for (int i = 0; i < length; i++) { | 9461 for (int i = 0; i < length; i++) { |
| 9363 iteration_order->set(i, Smi::FromInt(i)); | 9462 iteration_order->set(i, Smi::FromInt(i)); |
| 9364 } | 9463 } |
| 9365 | 9464 |
| 9366 // Allocate array with enumeration order. | 9465 // Allocate array with enumeration order. |
| 9367 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(length); | 9466 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length); |
| 9368 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9467 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9369 } | 9468 } |
| 9370 FixedArray* enumeration_order = FixedArray::cast(obj); | 9469 FixedArray* enumeration_order = FixedArray::cast(obj); |
| 9371 | 9470 |
| 9372 // Fill the enumeration order array with property details. | 9471 // Fill the enumeration order array with property details. |
| 9373 int capacity = HashTable<Shape, Key>::Capacity(); | 9472 int capacity = HashTable<Shape, Key>::Capacity(); |
| 9374 int pos = 0; | 9473 int pos = 0; |
| 9375 for (int i = 0; i < capacity; i++) { | 9474 for (int i = 0; i < capacity; i++) { |
| 9376 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { | 9475 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
| 9377 enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index())); | 9476 enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index())); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9418 } | 9517 } |
| 9419 } | 9518 } |
| 9420 return HashTable<Shape, Key>::EnsureCapacity(n, key); | 9519 return HashTable<Shape, Key>::EnsureCapacity(n, key); |
| 9421 } | 9520 } |
| 9422 | 9521 |
| 9423 | 9522 |
| 9424 void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) { | 9523 void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) { |
| 9425 // Do nothing if the interval [from, to) is empty. | 9524 // Do nothing if the interval [from, to) is empty. |
| 9426 if (from >= to) return; | 9525 if (from >= to) return; |
| 9427 | 9526 |
| 9527 Heap* heap = GetHeap(); |
| 9428 int removed_entries = 0; | 9528 int removed_entries = 0; |
| 9429 Object* sentinel = Heap::null_value(); | 9529 Object* sentinel = heap->null_value(); |
| 9430 int capacity = Capacity(); | 9530 int capacity = Capacity(); |
| 9431 for (int i = 0; i < capacity; i++) { | 9531 for (int i = 0; i < capacity; i++) { |
| 9432 Object* key = KeyAt(i); | 9532 Object* key = KeyAt(i); |
| 9433 if (key->IsNumber()) { | 9533 if (key->IsNumber()) { |
| 9434 uint32_t number = static_cast<uint32_t>(key->Number()); | 9534 uint32_t number = static_cast<uint32_t>(key->Number()); |
| 9435 if (from <= number && number < to) { | 9535 if (from <= number && number < to) { |
| 9436 SetEntry(i, sentinel, sentinel, Smi::FromInt(0)); | 9536 SetEntry(i, sentinel, sentinel, Smi::FromInt(0)); |
| 9437 removed_entries++; | 9537 removed_entries++; |
| 9438 } | 9538 } |
| 9439 } | 9539 } |
| 9440 } | 9540 } |
| 9441 | 9541 |
| 9442 // Update the number of elements. | 9542 // Update the number of elements. |
| 9443 ElementsRemoved(removed_entries); | 9543 ElementsRemoved(removed_entries); |
| 9444 } | 9544 } |
| 9445 | 9545 |
| 9446 | 9546 |
| 9447 template<typename Shape, typename Key> | 9547 template<typename Shape, typename Key> |
| 9448 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, | 9548 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, |
| 9449 JSObject::DeleteMode mode) { | 9549 JSObject::DeleteMode mode) { |
| 9550 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
| 9450 PropertyDetails details = DetailsAt(entry); | 9551 PropertyDetails details = DetailsAt(entry); |
| 9451 // Ignore attributes if forcing a deletion. | 9552 // Ignore attributes if forcing a deletion. |
| 9452 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { | 9553 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { |
| 9453 return Heap::false_value(); | 9554 return heap->false_value(); |
| 9454 } | 9555 } |
| 9455 SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0)); | 9556 SetEntry(entry, heap->null_value(), heap->null_value(), Smi::FromInt(0)); |
| 9456 HashTable<Shape, Key>::ElementRemoved(); | 9557 HashTable<Shape, Key>::ElementRemoved(); |
| 9457 return Heap::true_value(); | 9558 return heap->true_value(); |
| 9458 } | 9559 } |
| 9459 | 9560 |
| 9460 | 9561 |
| 9461 template<typename Shape, typename Key> | 9562 template<typename Shape, typename Key> |
| 9462 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { | 9563 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { |
| 9463 int entry = this->FindEntry(key); | 9564 int entry = this->FindEntry(key); |
| 9464 | 9565 |
| 9465 // If the entry is present set the value; | 9566 // If the entry is present set the value; |
| 9466 if (entry != Dictionary<Shape, Key>::kNotFound) { | 9567 if (entry != Dictionary<Shape, Key>::kNotFound) { |
| 9467 ValueAtPut(entry, value); | 9568 ValueAtPut(entry, value); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9660 storage->set(index++, k); | 9761 storage->set(index++, k); |
| 9661 } | 9762 } |
| 9662 } | 9763 } |
| 9663 ASSERT(storage->length() >= index); | 9764 ASSERT(storage->length() >= index); |
| 9664 } | 9765 } |
| 9665 | 9766 |
| 9666 | 9767 |
| 9667 // Backwards lookup (slow). | 9768 // Backwards lookup (slow). |
| 9668 template<typename Shape, typename Key> | 9769 template<typename Shape, typename Key> |
| 9669 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) { | 9770 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) { |
| 9771 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
| 9670 int capacity = HashTable<Shape, Key>::Capacity(); | 9772 int capacity = HashTable<Shape, Key>::Capacity(); |
| 9671 for (int i = 0; i < capacity; i++) { | 9773 for (int i = 0; i < capacity; i++) { |
| 9672 Object* k = HashTable<Shape, Key>::KeyAt(i); | 9774 Object* k = HashTable<Shape, Key>::KeyAt(i); |
| 9673 if (Dictionary<Shape, Key>::IsKey(k)) { | 9775 if (Dictionary<Shape, Key>::IsKey(k)) { |
| 9674 Object* e = ValueAt(i); | 9776 Object* e = ValueAt(i); |
| 9675 if (e->IsJSGlobalPropertyCell()) { | 9777 if (e->IsJSGlobalPropertyCell()) { |
| 9676 e = JSGlobalPropertyCell::cast(e)->value(); | 9778 e = JSGlobalPropertyCell::cast(e)->value(); |
| 9677 } | 9779 } |
| 9678 if (e == value) return k; | 9780 if (e == value) return k; |
| 9679 } | 9781 } |
| 9680 } | 9782 } |
| 9681 return Heap::undefined_value(); | 9783 return heap->undefined_value(); |
| 9682 } | 9784 } |
| 9683 | 9785 |
| 9684 | 9786 |
| 9685 MaybeObject* StringDictionary::TransformPropertiesToFastFor( | 9787 MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
| 9686 JSObject* obj, int unused_property_fields) { | 9788 JSObject* obj, int unused_property_fields) { |
| 9789 Heap* heap = GetHeap(); |
| 9687 // Make sure we preserve dictionary representation if there are too many | 9790 // Make sure we preserve dictionary representation if there are too many |
| 9688 // descriptors. | 9791 // descriptors. |
| 9689 if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj; | 9792 if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj; |
| 9690 | 9793 |
| 9691 // Figure out if it is necessary to generate new enumeration indices. | 9794 // Figure out if it is necessary to generate new enumeration indices. |
| 9692 int max_enumeration_index = | 9795 int max_enumeration_index = |
| 9693 NextEnumerationIndex() + | 9796 NextEnumerationIndex() + |
| 9694 (DescriptorArray::kMaxNumberOfDescriptors - | 9797 (DescriptorArray::kMaxNumberOfDescriptors - |
| 9695 NumberOfElements()); | 9798 NumberOfElements()); |
| 9696 if (!PropertyDetails::IsValidIndex(max_enumeration_index)) { | 9799 if (!PropertyDetails::IsValidIndex(max_enumeration_index)) { |
| 9697 Object* result; | 9800 Object* result; |
| 9698 { MaybeObject* maybe_result = GenerateNewEnumerationIndices(); | 9801 { MaybeObject* maybe_result = GenerateNewEnumerationIndices(); |
| 9699 if (!maybe_result->ToObject(&result)) return maybe_result; | 9802 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 9700 } | 9803 } |
| 9701 } | 9804 } |
| 9702 | 9805 |
| 9703 int instance_descriptor_length = 0; | 9806 int instance_descriptor_length = 0; |
| 9704 int number_of_fields = 0; | 9807 int number_of_fields = 0; |
| 9705 | 9808 |
| 9706 // Compute the length of the instance descriptor. | 9809 // Compute the length of the instance descriptor. |
| 9707 int capacity = Capacity(); | 9810 int capacity = Capacity(); |
| 9708 for (int i = 0; i < capacity; i++) { | 9811 for (int i = 0; i < capacity; i++) { |
| 9709 Object* k = KeyAt(i); | 9812 Object* k = KeyAt(i); |
| 9710 if (IsKey(k)) { | 9813 if (IsKey(k)) { |
| 9711 Object* value = ValueAt(i); | 9814 Object* value = ValueAt(i); |
| 9712 PropertyType type = DetailsAt(i).type(); | 9815 PropertyType type = DetailsAt(i).type(); |
| 9713 ASSERT(type != FIELD); | 9816 ASSERT(type != FIELD); |
| 9714 instance_descriptor_length++; | 9817 instance_descriptor_length++; |
| 9715 if (type == NORMAL && | 9818 if (type == NORMAL && |
| 9716 (!value->IsJSFunction() || Heap::InNewSpace(value))) { | 9819 (!value->IsJSFunction() || heap->InNewSpace(value))) { |
| 9717 number_of_fields += 1; | 9820 number_of_fields += 1; |
| 9718 } | 9821 } |
| 9719 } | 9822 } |
| 9720 } | 9823 } |
| 9721 | 9824 |
| 9722 // Allocate the instance descriptor. | 9825 // Allocate the instance descriptor. |
| 9723 Object* descriptors_unchecked; | 9826 Object* descriptors_unchecked; |
| 9724 { MaybeObject* maybe_descriptors_unchecked = | 9827 { MaybeObject* maybe_descriptors_unchecked = |
| 9725 DescriptorArray::Allocate(instance_descriptor_length); | 9828 DescriptorArray::Allocate(instance_descriptor_length); |
| 9726 if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { | 9829 if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { |
| 9727 return maybe_descriptors_unchecked; | 9830 return maybe_descriptors_unchecked; |
| 9728 } | 9831 } |
| 9729 } | 9832 } |
| 9730 DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked); | 9833 DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked); |
| 9731 | 9834 |
| 9732 int inobject_props = obj->map()->inobject_properties(); | 9835 int inobject_props = obj->map()->inobject_properties(); |
| 9733 int number_of_allocated_fields = | 9836 int number_of_allocated_fields = |
| 9734 number_of_fields + unused_property_fields - inobject_props; | 9837 number_of_fields + unused_property_fields - inobject_props; |
| 9735 if (number_of_allocated_fields < 0) { | 9838 if (number_of_allocated_fields < 0) { |
| 9736 // There is enough inobject space for all fields (including unused). | 9839 // There is enough inobject space for all fields (including unused). |
| 9737 number_of_allocated_fields = 0; | 9840 number_of_allocated_fields = 0; |
| 9738 unused_property_fields = inobject_props - number_of_fields; | 9841 unused_property_fields = inobject_props - number_of_fields; |
| 9739 } | 9842 } |
| 9740 | 9843 |
| 9741 // Allocate the fixed array for the fields. | 9844 // Allocate the fixed array for the fields. |
| 9742 Object* fields; | 9845 Object* fields; |
| 9743 { MaybeObject* maybe_fields = | 9846 { MaybeObject* maybe_fields = |
| 9744 Heap::AllocateFixedArray(number_of_allocated_fields); | 9847 heap->AllocateFixedArray(number_of_allocated_fields); |
| 9745 if (!maybe_fields->ToObject(&fields)) return maybe_fields; | 9848 if (!maybe_fields->ToObject(&fields)) return maybe_fields; |
| 9746 } | 9849 } |
| 9747 | 9850 |
| 9748 // Fill in the instance descriptor and the fields. | 9851 // Fill in the instance descriptor and the fields. |
| 9749 int next_descriptor = 0; | 9852 int next_descriptor = 0; |
| 9750 int current_offset = 0; | 9853 int current_offset = 0; |
| 9751 for (int i = 0; i < capacity; i++) { | 9854 for (int i = 0; i < capacity; i++) { |
| 9752 Object* k = KeyAt(i); | 9855 Object* k = KeyAt(i); |
| 9753 if (IsKey(k)) { | 9856 if (IsKey(k)) { |
| 9754 Object* value = ValueAt(i); | 9857 Object* value = ValueAt(i); |
| 9755 // Ensure the key is a symbol before writing into the instance descriptor. | 9858 // Ensure the key is a symbol before writing into the instance descriptor. |
| 9756 Object* key; | 9859 Object* key; |
| 9757 { MaybeObject* maybe_key = Heap::LookupSymbol(String::cast(k)); | 9860 { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k)); |
| 9758 if (!maybe_key->ToObject(&key)) return maybe_key; | 9861 if (!maybe_key->ToObject(&key)) return maybe_key; |
| 9759 } | 9862 } |
| 9760 PropertyDetails details = DetailsAt(i); | 9863 PropertyDetails details = DetailsAt(i); |
| 9761 PropertyType type = details.type(); | 9864 PropertyType type = details.type(); |
| 9762 | 9865 |
| 9763 if (value->IsJSFunction() && !Heap::InNewSpace(value)) { | 9866 if (value->IsJSFunction() && !heap->InNewSpace(value)) { |
| 9764 ConstantFunctionDescriptor d(String::cast(key), | 9867 ConstantFunctionDescriptor d(String::cast(key), |
| 9765 JSFunction::cast(value), | 9868 JSFunction::cast(value), |
| 9766 details.attributes(), | 9869 details.attributes(), |
| 9767 details.index()); | 9870 details.index()); |
| 9768 descriptors->Set(next_descriptor++, &d); | 9871 descriptors->Set(next_descriptor++, &d); |
| 9769 } else if (type == NORMAL) { | 9872 } else if (type == NORMAL) { |
| 9770 if (current_offset < inobject_props) { | 9873 if (current_offset < inobject_props) { |
| 9771 obj->InObjectPropertyAtPut(current_offset, | 9874 obj->InObjectPropertyAtPut(current_offset, |
| 9772 value, | 9875 value, |
| 9773 UPDATE_WRITE_BARRIER); | 9876 UPDATE_WRITE_BARRIER); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9824 | 9927 |
| 9825 // If there is no break point info object or no break points in the break | 9928 // If there is no break point info object or no break points in the break |
| 9826 // point info object there is no break point at this code position. | 9929 // point info object there is no break point at this code position. |
| 9827 if (break_point_info->IsUndefined()) return false; | 9930 if (break_point_info->IsUndefined()) return false; |
| 9828 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; | 9931 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; |
| 9829 } | 9932 } |
| 9830 | 9933 |
| 9831 | 9934 |
| 9832 // Get the break point info object for this code position. | 9935 // Get the break point info object for this code position. |
| 9833 Object* DebugInfo::GetBreakPointInfo(int code_position) { | 9936 Object* DebugInfo::GetBreakPointInfo(int code_position) { |
| 9937 Heap* heap = GetHeap(); |
| 9834 // Find the index of the break point info object for this code position. | 9938 // Find the index of the break point info object for this code position. |
| 9835 int index = GetBreakPointInfoIndex(code_position); | 9939 int index = GetBreakPointInfoIndex(code_position); |
| 9836 | 9940 |
| 9837 // Return the break point info object if any. | 9941 // Return the break point info object if any. |
| 9838 if (index == kNoBreakPointInfo) return Heap::undefined_value(); | 9942 if (index == kNoBreakPointInfo) return heap->undefined_value(); |
| 9839 return BreakPointInfo::cast(break_points()->get(index)); | 9943 return BreakPointInfo::cast(break_points()->get(index)); |
| 9840 } | 9944 } |
| 9841 | 9945 |
| 9842 | 9946 |
| 9843 // Clear a break point at the specified code position. | 9947 // Clear a break point at the specified code position. |
| 9844 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info, | 9948 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info, |
| 9845 int code_position, | 9949 int code_position, |
| 9846 Handle<Object> break_point_object) { | 9950 Handle<Object> break_point_object) { |
| 9847 Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position)); | 9951 Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position)); |
| 9848 if (break_point_info->IsUndefined()) return; | 9952 if (break_point_info->IsUndefined()) return; |
| 9849 BreakPointInfo::ClearBreakPoint( | 9953 BreakPointInfo::ClearBreakPoint( |
| 9850 Handle<BreakPointInfo>::cast(break_point_info), | 9954 Handle<BreakPointInfo>::cast(break_point_info), |
| 9851 break_point_object); | 9955 break_point_object); |
| 9852 } | 9956 } |
| 9853 | 9957 |
| 9854 | 9958 |
| 9855 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, | 9959 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, |
| 9856 int code_position, | 9960 int code_position, |
| 9857 int source_position, | 9961 int source_position, |
| 9858 int statement_position, | 9962 int statement_position, |
| 9859 Handle<Object> break_point_object) { | 9963 Handle<Object> break_point_object) { |
| 9964 Isolate* isolate = Isolate::Current(); |
| 9860 Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position)); | 9965 Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position)); |
| 9861 if (!break_point_info->IsUndefined()) { | 9966 if (!break_point_info->IsUndefined()) { |
| 9862 BreakPointInfo::SetBreakPoint( | 9967 BreakPointInfo::SetBreakPoint( |
| 9863 Handle<BreakPointInfo>::cast(break_point_info), | 9968 Handle<BreakPointInfo>::cast(break_point_info), |
| 9864 break_point_object); | 9969 break_point_object); |
| 9865 return; | 9970 return; |
| 9866 } | 9971 } |
| 9867 | 9972 |
| 9868 // Adding a new break point for a code position which did not have any | 9973 // Adding a new break point for a code position which did not have any |
| 9869 // break points before. Try to find a free slot. | 9974 // break points before. Try to find a free slot. |
| 9870 int index = kNoBreakPointInfo; | 9975 int index = kNoBreakPointInfo; |
| 9871 for (int i = 0; i < debug_info->break_points()->length(); i++) { | 9976 for (int i = 0; i < debug_info->break_points()->length(); i++) { |
| 9872 if (debug_info->break_points()->get(i)->IsUndefined()) { | 9977 if (debug_info->break_points()->get(i)->IsUndefined()) { |
| 9873 index = i; | 9978 index = i; |
| 9874 break; | 9979 break; |
| 9875 } | 9980 } |
| 9876 } | 9981 } |
| 9877 if (index == kNoBreakPointInfo) { | 9982 if (index == kNoBreakPointInfo) { |
| 9878 // No free slot - extend break point info array. | 9983 // No free slot - extend break point info array. |
| 9879 Handle<FixedArray> old_break_points = | 9984 Handle<FixedArray> old_break_points = |
| 9880 Handle<FixedArray>(FixedArray::cast(debug_info->break_points())); | 9985 Handle<FixedArray>(FixedArray::cast(debug_info->break_points())); |
| 9881 Handle<FixedArray> new_break_points = | 9986 Handle<FixedArray> new_break_points = |
| 9882 Factory::NewFixedArray(old_break_points->length() + | 9987 isolate->factory()->NewFixedArray( |
| 9883 Debug::kEstimatedNofBreakPointsInFunction); | 9988 old_break_points->length() + |
| 9989 Debug::kEstimatedNofBreakPointsInFunction); |
| 9884 | 9990 |
| 9885 debug_info->set_break_points(*new_break_points); | 9991 debug_info->set_break_points(*new_break_points); |
| 9886 for (int i = 0; i < old_break_points->length(); i++) { | 9992 for (int i = 0; i < old_break_points->length(); i++) { |
| 9887 new_break_points->set(i, old_break_points->get(i)); | 9993 new_break_points->set(i, old_break_points->get(i)); |
| 9888 } | 9994 } |
| 9889 index = old_break_points->length(); | 9995 index = old_break_points->length(); |
| 9890 } | 9996 } |
| 9891 ASSERT(index != kNoBreakPointInfo); | 9997 ASSERT(index != kNoBreakPointInfo); |
| 9892 | 9998 |
| 9893 // Allocate new BreakPointInfo object and set the break point. | 9999 // Allocate new BreakPointInfo object and set the break point. |
| 9894 Handle<BreakPointInfo> new_break_point_info = | 10000 Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast( |
| 9895 Handle<BreakPointInfo>::cast(Factory::NewStruct(BREAK_POINT_INFO_TYPE)); | 10001 isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE)); |
| 9896 new_break_point_info->set_code_position(Smi::FromInt(code_position)); | 10002 new_break_point_info->set_code_position(Smi::FromInt(code_position)); |
| 9897 new_break_point_info->set_source_position(Smi::FromInt(source_position)); | 10003 new_break_point_info->set_source_position(Smi::FromInt(source_position)); |
| 9898 new_break_point_info-> | 10004 new_break_point_info-> |
| 9899 set_statement_position(Smi::FromInt(statement_position)); | 10005 set_statement_position(Smi::FromInt(statement_position)); |
| 9900 new_break_point_info->set_break_point_objects(Heap::undefined_value()); | 10006 new_break_point_info->set_break_point_objects( |
| 10007 isolate->heap()->undefined_value()); |
| 9901 BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object); | 10008 BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object); |
| 9902 debug_info->break_points()->set(index, *new_break_point_info); | 10009 debug_info->break_points()->set(index, *new_break_point_info); |
| 9903 } | 10010 } |
| 9904 | 10011 |
| 9905 | 10012 |
| 9906 // Get the break point objects for a code position. | 10013 // Get the break point objects for a code position. |
| 9907 Object* DebugInfo::GetBreakPointObjects(int code_position) { | 10014 Object* DebugInfo::GetBreakPointObjects(int code_position) { |
| 10015 Heap* heap = GetHeap(); |
| 9908 Object* break_point_info = GetBreakPointInfo(code_position); | 10016 Object* break_point_info = GetBreakPointInfo(code_position); |
| 9909 if (break_point_info->IsUndefined()) { | 10017 if (break_point_info->IsUndefined()) { |
| 9910 return Heap::undefined_value(); | 10018 return heap->undefined_value(); |
| 9911 } | 10019 } |
| 9912 return BreakPointInfo::cast(break_point_info)->break_point_objects(); | 10020 return BreakPointInfo::cast(break_point_info)->break_point_objects(); |
| 9913 } | 10021 } |
| 9914 | 10022 |
| 9915 | 10023 |
| 9916 // Get the total number of break points. | 10024 // Get the total number of break points. |
| 9917 int DebugInfo::GetBreakPointCount() { | 10025 int DebugInfo::GetBreakPointCount() { |
| 9918 if (break_points()->IsUndefined()) return 0; | 10026 if (break_points()->IsUndefined()) return 0; |
| 9919 int count = 0; | 10027 int count = 0; |
| 9920 for (int i = 0; i < break_points()->length(); i++) { | 10028 for (int i = 0; i < break_points()->length(); i++) { |
| 9921 if (!break_points()->get(i)->IsUndefined()) { | 10029 if (!break_points()->get(i)->IsUndefined()) { |
| 9922 BreakPointInfo* break_point_info = | 10030 BreakPointInfo* break_point_info = |
| 9923 BreakPointInfo::cast(break_points()->get(i)); | 10031 BreakPointInfo::cast(break_points()->get(i)); |
| 9924 count += break_point_info->GetBreakPointCount(); | 10032 count += break_point_info->GetBreakPointCount(); |
| 9925 } | 10033 } |
| 9926 } | 10034 } |
| 9927 return count; | 10035 return count; |
| 9928 } | 10036 } |
| 9929 | 10037 |
| 9930 | 10038 |
| 9931 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info, | 10039 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info, |
| 9932 Handle<Object> break_point_object) { | 10040 Handle<Object> break_point_object) { |
| 9933 if (debug_info->break_points()->IsUndefined()) return Heap::undefined_value(); | 10041 Heap* heap = Isolate::Current()->heap(); |
| 10042 if (debug_info->break_points()->IsUndefined()) return heap->undefined_value(); |
| 9934 for (int i = 0; i < debug_info->break_points()->length(); i++) { | 10043 for (int i = 0; i < debug_info->break_points()->length(); i++) { |
| 9935 if (!debug_info->break_points()->get(i)->IsUndefined()) { | 10044 if (!debug_info->break_points()->get(i)->IsUndefined()) { |
| 9936 Handle<BreakPointInfo> break_point_info = | 10045 Handle<BreakPointInfo> break_point_info = |
| 9937 Handle<BreakPointInfo>(BreakPointInfo::cast( | 10046 Handle<BreakPointInfo>(BreakPointInfo::cast( |
| 9938 debug_info->break_points()->get(i))); | 10047 debug_info->break_points()->get(i))); |
| 9939 if (BreakPointInfo::HasBreakPointObject(break_point_info, | 10048 if (BreakPointInfo::HasBreakPointObject(break_point_info, |
| 9940 break_point_object)) { | 10049 break_point_object)) { |
| 9941 return *break_point_info; | 10050 return *break_point_info; |
| 9942 } | 10051 } |
| 9943 } | 10052 } |
| 9944 } | 10053 } |
| 9945 return Heap::undefined_value(); | 10054 return heap->undefined_value(); |
| 9946 } | 10055 } |
| 9947 | 10056 |
| 9948 | 10057 |
| 9949 // Find the index of the break point info object for the specified code | 10058 // Find the index of the break point info object for the specified code |
| 9950 // position. | 10059 // position. |
| 9951 int DebugInfo::GetBreakPointInfoIndex(int code_position) { | 10060 int DebugInfo::GetBreakPointInfoIndex(int code_position) { |
| 9952 if (break_points()->IsUndefined()) return kNoBreakPointInfo; | 10061 if (break_points()->IsUndefined()) return kNoBreakPointInfo; |
| 9953 for (int i = 0; i < break_points()->length(); i++) { | 10062 for (int i = 0; i < break_points()->length(); i++) { |
| 9954 if (!break_points()->get(i)->IsUndefined()) { | 10063 if (!break_points()->get(i)->IsUndefined()) { |
| 9955 BreakPointInfo* break_point_info = | 10064 BreakPointInfo* break_point_info = |
| 9956 BreakPointInfo::cast(break_points()->get(i)); | 10065 BreakPointInfo::cast(break_points()->get(i)); |
| 9957 if (break_point_info->code_position()->value() == code_position) { | 10066 if (break_point_info->code_position()->value() == code_position) { |
| 9958 return i; | 10067 return i; |
| 9959 } | 10068 } |
| 9960 } | 10069 } |
| 9961 } | 10070 } |
| 9962 return kNoBreakPointInfo; | 10071 return kNoBreakPointInfo; |
| 9963 } | 10072 } |
| 9964 | 10073 |
| 9965 | 10074 |
| 9966 // Remove the specified break point object. | 10075 // Remove the specified break point object. |
| 9967 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info, | 10076 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info, |
| 9968 Handle<Object> break_point_object) { | 10077 Handle<Object> break_point_object) { |
| 10078 Isolate* isolate = Isolate::Current(); |
| 9969 // If there are no break points just ignore. | 10079 // If there are no break points just ignore. |
| 9970 if (break_point_info->break_point_objects()->IsUndefined()) return; | 10080 if (break_point_info->break_point_objects()->IsUndefined()) return; |
| 9971 // If there is a single break point clear it if it is the same. | 10081 // If there is a single break point clear it if it is the same. |
| 9972 if (!break_point_info->break_point_objects()->IsFixedArray()) { | 10082 if (!break_point_info->break_point_objects()->IsFixedArray()) { |
| 9973 if (break_point_info->break_point_objects() == *break_point_object) { | 10083 if (break_point_info->break_point_objects() == *break_point_object) { |
| 9974 break_point_info->set_break_point_objects(Heap::undefined_value()); | 10084 break_point_info->set_break_point_objects( |
| 10085 isolate->heap()->undefined_value()); |
| 9975 } | 10086 } |
| 9976 return; | 10087 return; |
| 9977 } | 10088 } |
| 9978 // If there are multiple break points shrink the array | 10089 // If there are multiple break points shrink the array |
| 9979 ASSERT(break_point_info->break_point_objects()->IsFixedArray()); | 10090 ASSERT(break_point_info->break_point_objects()->IsFixedArray()); |
| 9980 Handle<FixedArray> old_array = | 10091 Handle<FixedArray> old_array = |
| 9981 Handle<FixedArray>( | 10092 Handle<FixedArray>( |
| 9982 FixedArray::cast(break_point_info->break_point_objects())); | 10093 FixedArray::cast(break_point_info->break_point_objects())); |
| 9983 Handle<FixedArray> new_array = | 10094 Handle<FixedArray> new_array = |
| 9984 Factory::NewFixedArray(old_array->length() - 1); | 10095 isolate->factory()->NewFixedArray(old_array->length() - 1); |
| 9985 int found_count = 0; | 10096 int found_count = 0; |
| 9986 for (int i = 0; i < old_array->length(); i++) { | 10097 for (int i = 0; i < old_array->length(); i++) { |
| 9987 if (old_array->get(i) == *break_point_object) { | 10098 if (old_array->get(i) == *break_point_object) { |
| 9988 ASSERT(found_count == 0); | 10099 ASSERT(found_count == 0); |
| 9989 found_count++; | 10100 found_count++; |
| 9990 } else { | 10101 } else { |
| 9991 new_array->set(i - found_count, old_array->get(i)); | 10102 new_array->set(i - found_count, old_array->get(i)); |
| 9992 } | 10103 } |
| 9993 } | 10104 } |
| 9994 // If the break point was found in the list change it. | 10105 // If the break point was found in the list change it. |
| 9995 if (found_count > 0) break_point_info->set_break_point_objects(*new_array); | 10106 if (found_count > 0) break_point_info->set_break_point_objects(*new_array); |
| 9996 } | 10107 } |
| 9997 | 10108 |
| 9998 | 10109 |
| 9999 // Add the specified break point object. | 10110 // Add the specified break point object. |
| 10000 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info, | 10111 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info, |
| 10001 Handle<Object> break_point_object) { | 10112 Handle<Object> break_point_object) { |
| 10002 // If there was no break point objects before just set it. | 10113 // If there was no break point objects before just set it. |
| 10003 if (break_point_info->break_point_objects()->IsUndefined()) { | 10114 if (break_point_info->break_point_objects()->IsUndefined()) { |
| 10004 break_point_info->set_break_point_objects(*break_point_object); | 10115 break_point_info->set_break_point_objects(*break_point_object); |
| 10005 return; | 10116 return; |
| 10006 } | 10117 } |
| 10007 // If the break point object is the same as before just ignore. | 10118 // If the break point object is the same as before just ignore. |
| 10008 if (break_point_info->break_point_objects() == *break_point_object) return; | 10119 if (break_point_info->break_point_objects() == *break_point_object) return; |
| 10009 // If there was one break point object before replace with array. | 10120 // If there was one break point object before replace with array. |
| 10010 if (!break_point_info->break_point_objects()->IsFixedArray()) { | 10121 if (!break_point_info->break_point_objects()->IsFixedArray()) { |
| 10011 Handle<FixedArray> array = Factory::NewFixedArray(2); | 10122 Handle<FixedArray> array = FACTORY->NewFixedArray(2); |
| 10012 array->set(0, break_point_info->break_point_objects()); | 10123 array->set(0, break_point_info->break_point_objects()); |
| 10013 array->set(1, *break_point_object); | 10124 array->set(1, *break_point_object); |
| 10014 break_point_info->set_break_point_objects(*array); | 10125 break_point_info->set_break_point_objects(*array); |
| 10015 return; | 10126 return; |
| 10016 } | 10127 } |
| 10017 // If there was more than one break point before extend array. | 10128 // If there was more than one break point before extend array. |
| 10018 Handle<FixedArray> old_array = | 10129 Handle<FixedArray> old_array = |
| 10019 Handle<FixedArray>( | 10130 Handle<FixedArray>( |
| 10020 FixedArray::cast(break_point_info->break_point_objects())); | 10131 FixedArray::cast(break_point_info->break_point_objects())); |
| 10021 Handle<FixedArray> new_array = | 10132 Handle<FixedArray> new_array = |
| 10022 Factory::NewFixedArray(old_array->length() + 1); | 10133 FACTORY->NewFixedArray(old_array->length() + 1); |
| 10023 for (int i = 0; i < old_array->length(); i++) { | 10134 for (int i = 0; i < old_array->length(); i++) { |
| 10024 // If the break point was there before just ignore. | 10135 // If the break point was there before just ignore. |
| 10025 if (old_array->get(i) == *break_point_object) return; | 10136 if (old_array->get(i) == *break_point_object) return; |
| 10026 new_array->set(i, old_array->get(i)); | 10137 new_array->set(i, old_array->get(i)); |
| 10027 } | 10138 } |
| 10028 // Add the new break point. | 10139 // Add the new break point. |
| 10029 new_array->set(old_array->length(), *break_point_object); | 10140 new_array->set(old_array->length(), *break_point_object); |
| 10030 break_point_info->set_break_point_objects(*new_array); | 10141 break_point_info->set_break_point_objects(*new_array); |
| 10031 } | 10142 } |
| 10032 | 10143 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 10057 if (break_point_objects()->IsUndefined()) return 0; | 10168 if (break_point_objects()->IsUndefined()) return 0; |
| 10058 // Single beak point. | 10169 // Single beak point. |
| 10059 if (!break_point_objects()->IsFixedArray()) return 1; | 10170 if (!break_point_objects()->IsFixedArray()) return 1; |
| 10060 // Multiple break points. | 10171 // Multiple break points. |
| 10061 return FixedArray::cast(break_point_objects())->length(); | 10172 return FixedArray::cast(break_point_objects())->length(); |
| 10062 } | 10173 } |
| 10063 #endif | 10174 #endif |
| 10064 | 10175 |
| 10065 | 10176 |
| 10066 } } // namespace v8::internal | 10177 } } // namespace v8::internal |
| OLD | NEW |