blob: b03efbd57a21c97789a825cd5bca75880acafdf3 [file] [log] [blame]
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "accessors.h"
31#include "api.h"
32#include "arguments.h"
33#include "bootstrapper.h"
34#include "compiler.h"
35#include "debug.h"
36#include "execution.h"
37#include "global-handles.h"
38#include "natives.h"
39#include "runtime.h"
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080040#include "string-search.h"
Steve Blockd0582a62009-12-15 09:54:21 +000041#include "stub-cache.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010042#include "vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000043
44namespace v8 {
45namespace internal {
46
47
Steve Blocka7e24c12009-10-30 11:49:00 +000048int HandleScope::NumberOfHandles() {
Steve Block44f0eee2011-05-26 01:26:41 +010049 Isolate* isolate = Isolate::Current();
50 HandleScopeImplementer* impl = isolate->handle_scope_implementer();
51 int n = impl->blocks()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +000052 if (n == 0) return 0;
Steve Blockd0582a62009-12-15 09:54:21 +000053 return ((n - 1) * kHandleBlockSize) + static_cast<int>(
Steve Block44f0eee2011-05-26 01:26:41 +010054 (isolate->handle_scope_data()->next - impl->blocks()->last()));
Steve Blocka7e24c12009-10-30 11:49:00 +000055}
56
57
58Object** HandleScope::Extend() {
Steve Block44f0eee2011-05-26 01:26:41 +010059 Isolate* isolate = Isolate::Current();
60 v8::ImplementationUtilities::HandleScopeData* current =
61 isolate->handle_scope_data();
Steve Blocka7e24c12009-10-30 11:49:00 +000062
Steve Block44f0eee2011-05-26 01:26:41 +010063 Object** result = current->next;
64
65 ASSERT(result == current->limit);
Steve Blocka7e24c12009-10-30 11:49:00 +000066 // Make sure there's at least one scope on the stack and that the
67 // top of the scope stack isn't a barrier.
Steve Block44f0eee2011-05-26 01:26:41 +010068 if (current->level == 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +000069 Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
70 "Cannot create a handle without a HandleScope");
71 return NULL;
72 }
Steve Block44f0eee2011-05-26 01:26:41 +010073 HandleScopeImplementer* impl = isolate->handle_scope_implementer();
Steve Blocka7e24c12009-10-30 11:49:00 +000074 // If there's more room in the last block, we use that. This is used
75 // for fast creation of scopes after scope barriers.
76 if (!impl->blocks()->is_empty()) {
77 Object** limit = &impl->blocks()->last()[kHandleBlockSize];
Steve Block44f0eee2011-05-26 01:26:41 +010078 if (current->limit != limit) {
79 current->limit = limit;
80 ASSERT(limit - current->next < kHandleBlockSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000081 }
82 }
83
84 // If we still haven't found a slot for the handle, we extend the
85 // current handle scope by allocating a new handle block.
Steve Block44f0eee2011-05-26 01:26:41 +010086 if (result == current->limit) {
Steve Blocka7e24c12009-10-30 11:49:00 +000087 // If there's a spare block, use it for growing the current scope.
88 result = impl->GetSpareOrNewBlock();
89 // Add the extension to the global list of blocks, but count the
90 // extension as part of the current scope.
91 impl->blocks()->Add(result);
Steve Block44f0eee2011-05-26 01:26:41 +010092 current->limit = &result[kHandleBlockSize];
Steve Blocka7e24c12009-10-30 11:49:00 +000093 }
94
95 return result;
96}
97
98
Steve Block44f0eee2011-05-26 01:26:41 +010099void HandleScope::DeleteExtensions(Isolate* isolate) {
100 ASSERT(isolate == Isolate::Current());
101 v8::ImplementationUtilities::HandleScopeData* current =
102 isolate->handle_scope_data();
103 isolate->handle_scope_implementer()->DeleteExtensions(current->limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000104}
105
106
107void HandleScope::ZapRange(Object** start, Object** end) {
John Reck59135872010-11-02 12:39:01 -0700108 ASSERT(end - start <= kHandleBlockSize);
109 for (Object** p = start; p != end; p++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 *reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue;
111 }
112}
113
114
John Reck59135872010-11-02 12:39:01 -0700115Address HandleScope::current_level_address() {
Steve Block44f0eee2011-05-26 01:26:41 +0100116 return reinterpret_cast<Address>(
117 &Isolate::Current()->handle_scope_data()->level);
Steve Blockd0582a62009-12-15 09:54:21 +0000118}
119
120
121Address HandleScope::current_next_address() {
Steve Block44f0eee2011-05-26 01:26:41 +0100122 return reinterpret_cast<Address>(
123 &Isolate::Current()->handle_scope_data()->next);
Steve Blockd0582a62009-12-15 09:54:21 +0000124}
125
126
127Address HandleScope::current_limit_address() {
Steve Block44f0eee2011-05-26 01:26:41 +0100128 return reinterpret_cast<Address>(
129 &Isolate::Current()->handle_scope_data()->limit);
Steve Blockd0582a62009-12-15 09:54:21 +0000130}
131
132
Steve Blocka7e24c12009-10-30 11:49:00 +0000133Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content,
134 Handle<JSArray> array) {
Steve Block44f0eee2011-05-26 01:26:41 +0100135 CALL_HEAP_FUNCTION(content->GetIsolate(),
136 content->AddKeysFromJSArray(*array), FixedArray);
Steve Blocka7e24c12009-10-30 11:49:00 +0000137}
138
139
140Handle<FixedArray> UnionOfKeys(Handle<FixedArray> first,
141 Handle<FixedArray> second) {
Steve Block44f0eee2011-05-26 01:26:41 +0100142 CALL_HEAP_FUNCTION(first->GetIsolate(),
143 first->UnionOfKeys(*second), FixedArray);
Steve Blocka7e24c12009-10-30 11:49:00 +0000144}
145
146
147Handle<JSGlobalProxy> ReinitializeJSGlobalProxy(
148 Handle<JSFunction> constructor,
149 Handle<JSGlobalProxy> global) {
Steve Block44f0eee2011-05-26 01:26:41 +0100150 CALL_HEAP_FUNCTION(
151 constructor->GetIsolate(),
152 constructor->GetHeap()->ReinitializeJSGlobalProxy(*constructor, *global),
153 JSGlobalProxy);
Steve Blocka7e24c12009-10-30 11:49:00 +0000154}
155
156
157void SetExpectedNofProperties(Handle<JSFunction> func, int nof) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100158 // If objects constructed from this function exist then changing
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800159 // 'estimated_nof_properties' is dangerous since the previous value might
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100160 // have been compiled into the fast construct stub. More over, the inobject
161 // slack tracking logic might have adjusted the previous value, so even
162 // passing the same value is risky.
163 if (func->shared()->live_objects_may_exist()) return;
164
Steve Blocka7e24c12009-10-30 11:49:00 +0000165 func->shared()->set_expected_nof_properties(nof);
166 if (func->has_initial_map()) {
167 Handle<Map> new_initial_map =
Steve Block44f0eee2011-05-26 01:26:41 +0100168 func->GetIsolate()->factory()->CopyMapDropTransitions(
169 Handle<Map>(func->initial_map()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 new_initial_map->set_unused_property_fields(nof);
171 func->set_initial_map(*new_initial_map);
172 }
173}
174
175
176void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100177 CALL_HEAP_FUNCTION_VOID(func->GetIsolate(),
178 func->SetPrototype(*value));
Steve Blocka7e24c12009-10-30 11:49:00 +0000179}
180
181
182static int ExpectedNofPropertiesFromEstimate(int estimate) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100183 // If no properties are added in the constructor, they are more likely
184 // to be added later.
185 if (estimate == 0) estimate = 2;
186
187 // We do not shrink objects that go into a snapshot (yet), so we adjust
188 // the estimate conservatively.
189 if (Serializer::enabled()) return estimate + 2;
190
191 // Inobject slack tracking will reclaim redundant inobject space later,
192 // so we can afford to adjust the estimate generously.
Ben Murdochf87a2032010-10-22 12:50:53 +0100193 return estimate + 8;
Steve Blocka7e24c12009-10-30 11:49:00 +0000194}
195
196
197void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
198 int estimate) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100199 // See the comment in SetExpectedNofProperties.
200 if (shared->live_objects_may_exist()) return;
201
Steve Blocka7e24c12009-10-30 11:49:00 +0000202 shared->set_expected_nof_properties(
203 ExpectedNofPropertiesFromEstimate(estimate));
204}
205
206
Steve Blocka7e24c12009-10-30 11:49:00 +0000207void NormalizeProperties(Handle<JSObject> object,
208 PropertyNormalizationMode mode,
209 int expected_additional_properties) {
Steve Block44f0eee2011-05-26 01:26:41 +0100210 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
211 object->NormalizeProperties(
212 mode,
213 expected_additional_properties));
Steve Blocka7e24c12009-10-30 11:49:00 +0000214}
215
216
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000217Handle<NumberDictionary> NormalizeElements(Handle<JSObject> object) {
218 CALL_HEAP_FUNCTION(object->GetIsolate(),
219 object->NormalizeElements(),
220 NumberDictionary);
Steve Blocka7e24c12009-10-30 11:49:00 +0000221}
222
223
224void TransformToFastProperties(Handle<JSObject> object,
225 int unused_property_fields) {
226 CALL_HEAP_FUNCTION_VOID(
Steve Block44f0eee2011-05-26 01:26:41 +0100227 object->GetIsolate(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000228 object->TransformToFastProperties(unused_property_fields));
229}
230
231
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000232Handle<NumberDictionary> NumberDictionarySet(
233 Handle<NumberDictionary> dictionary,
234 uint32_t index,
235 Handle<Object> value,
236 PropertyDetails details) {
237 CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
238 dictionary->Set(index, *value, details),
239 NumberDictionary);
John Reck59135872010-11-02 12:39:01 -0700240}
241
242
Steve Blocka7e24c12009-10-30 11:49:00 +0000243void FlattenString(Handle<String> string) {
Steve Block44f0eee2011-05-26 01:26:41 +0100244 CALL_HEAP_FUNCTION_VOID(string->GetIsolate(), string->TryFlatten());
Steve Block8defd9f2010-07-08 12:39:36 +0100245}
246
247
248Handle<String> FlattenGetString(Handle<String> string) {
Steve Block44f0eee2011-05-26 01:26:41 +0100249 CALL_HEAP_FUNCTION(string->GetIsolate(), string->TryFlatten(), String);
Steve Blocka7e24c12009-10-30 11:49:00 +0000250}
251
252
253Handle<Object> SetPrototype(Handle<JSFunction> function,
254 Handle<Object> prototype) {
Steve Block6ded16b2010-05-10 14:33:55 +0100255 ASSERT(function->should_have_prototype());
Steve Block44f0eee2011-05-26 01:26:41 +0100256 CALL_HEAP_FUNCTION(function->GetIsolate(),
257 Accessors::FunctionSetPrototype(*function,
Steve Blocka7e24c12009-10-30 11:49:00 +0000258 *prototype,
259 NULL),
260 Object);
261}
262
263
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000264Handle<Object> SetProperty(Handle<JSReceiver> object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000265 Handle<String> key,
266 Handle<Object> value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100267 PropertyAttributes attributes,
268 StrictModeFlag strict_mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100269 CALL_HEAP_FUNCTION(object->GetIsolate(),
270 object->SetProperty(*key, *value, attributes, strict_mode),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100271 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000272}
273
274
275Handle<Object> SetProperty(Handle<Object> object,
276 Handle<Object> key,
277 Handle<Object> value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100278 PropertyAttributes attributes,
279 StrictModeFlag strict_mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100280 Isolate* isolate = Isolate::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000281 CALL_HEAP_FUNCTION(
Steve Block44f0eee2011-05-26 01:26:41 +0100282 isolate,
283 Runtime::SetObjectProperty(
284 isolate, object, key, value, attributes, strict_mode),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100285 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000286}
287
288
289Handle<Object> ForceSetProperty(Handle<JSObject> object,
290 Handle<Object> key,
291 Handle<Object> value,
292 PropertyAttributes attributes) {
Steve Block44f0eee2011-05-26 01:26:41 +0100293 Isolate* isolate = object->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +0000294 CALL_HEAP_FUNCTION(
Steve Block44f0eee2011-05-26 01:26:41 +0100295 isolate,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100296 Runtime::ForceSetObjectProperty(
Steve Block44f0eee2011-05-26 01:26:41 +0100297 isolate, object, key, value, attributes),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100298 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000299}
300
301
Andrei Popescu31002712010-02-23 13:46:05 +0000302Handle<Object> SetNormalizedProperty(Handle<JSObject> object,
303 Handle<String> key,
304 Handle<Object> value,
305 PropertyDetails details) {
Steve Block44f0eee2011-05-26 01:26:41 +0100306 CALL_HEAP_FUNCTION(object->GetIsolate(),
307 object->SetNormalizedProperty(*key, *value, details),
Andrei Popescu31002712010-02-23 13:46:05 +0000308 Object);
309}
310
311
Steve Blocka7e24c12009-10-30 11:49:00 +0000312Handle<Object> ForceDeleteProperty(Handle<JSObject> object,
313 Handle<Object> key) {
Steve Block44f0eee2011-05-26 01:26:41 +0100314 Isolate* isolate = object->GetIsolate();
315 CALL_HEAP_FUNCTION(isolate,
316 Runtime::ForceDeleteObjectProperty(isolate, object, key),
317 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000318}
319
320
Ben Murdoch086aeea2011-05-13 15:57:08 +0100321Handle<Object> SetLocalPropertyIgnoreAttributes(
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 Handle<JSObject> object,
323 Handle<String> key,
324 Handle<Object> value,
325 PropertyAttributes attributes) {
Steve Block44f0eee2011-05-26 01:26:41 +0100326 CALL_HEAP_FUNCTION(
327 object->GetIsolate(),
328 object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
329 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000330}
331
332
Steve Block1e0659c2011-05-24 12:43:12 +0100333void SetLocalPropertyNoThrow(Handle<JSObject> object,
334 Handle<String> key,
335 Handle<Object> value,
336 PropertyAttributes attributes) {
Steve Block44f0eee2011-05-26 01:26:41 +0100337 Isolate* isolate = object->GetIsolate();
338 ASSERT(!isolate->has_pending_exception());
Steve Block1e0659c2011-05-24 12:43:12 +0100339 CHECK(!SetLocalPropertyIgnoreAttributes(
340 object, key, value, attributes).is_null());
Steve Block44f0eee2011-05-26 01:26:41 +0100341 CHECK(!isolate->has_pending_exception());
Steve Block1e0659c2011-05-24 12:43:12 +0100342}
343
344
Steve Blocka7e24c12009-10-30 11:49:00 +0000345Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
346 Handle<String> key,
347 Handle<Object> value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100348 PropertyAttributes attributes,
349 StrictModeFlag strict_mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100350 CALL_HEAP_FUNCTION(object->GetIsolate(),
351 object->SetPropertyWithInterceptor(*key,
Steve Blocka7e24c12009-10-30 11:49:00 +0000352 *value,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100353 attributes,
354 strict_mode),
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 Object);
356}
357
358
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000359Handle<Object> GetProperty(Handle<JSReceiver> obj,
Steve Blocka7e24c12009-10-30 11:49:00 +0000360 const char* name) {
Steve Block44f0eee2011-05-26 01:26:41 +0100361 Isolate* isolate = obj->GetIsolate();
362 Handle<String> str = isolate->factory()->LookupAsciiSymbol(name);
363 CALL_HEAP_FUNCTION(isolate, obj->GetProperty(*str), Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000364}
365
366
367Handle<Object> GetProperty(Handle<Object> obj,
368 Handle<Object> key) {
Steve Block44f0eee2011-05-26 01:26:41 +0100369 Isolate* isolate = Isolate::Current();
370 CALL_HEAP_FUNCTION(isolate,
371 Runtime::GetObjectProperty(isolate, obj, key), Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000372}
373
374
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000375Handle<Object> GetProperty(Handle<JSReceiver> obj,
Ben Murdoch8b112d22011-06-08 16:22:53 +0100376 Handle<String> name,
377 LookupResult* result) {
378 PropertyAttributes attributes;
379 Isolate* isolate = Isolate::Current();
380 CALL_HEAP_FUNCTION(isolate,
381 obj->GetProperty(*obj, result, *name, &attributes),
382 Object);
383}
384
385
Steve Block6ded16b2010-05-10 14:33:55 +0100386Handle<Object> GetElement(Handle<Object> obj,
387 uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +0100388 Isolate* isolate = Isolate::Current();
389 CALL_HEAP_FUNCTION(isolate, Runtime::GetElement(obj, index), Object);
Steve Block6ded16b2010-05-10 14:33:55 +0100390}
391
392
Steve Blocka7e24c12009-10-30 11:49:00 +0000393Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
394 Handle<JSObject> holder,
395 Handle<String> name,
396 PropertyAttributes* attributes) {
Steve Block44f0eee2011-05-26 01:26:41 +0100397 Isolate* isolate = receiver->GetIsolate();
398 CALL_HEAP_FUNCTION(isolate,
399 holder->GetPropertyWithInterceptor(*receiver,
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 *name,
401 attributes),
402 Object);
403}
404
405
406Handle<Object> GetPrototype(Handle<Object> obj) {
407 Handle<Object> result(obj->GetPrototype());
408 return result;
409}
410
411
Andrei Popescu402d9372010-02-26 13:31:12 +0000412Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value) {
413 const bool skip_hidden_prototypes = false;
Steve Block44f0eee2011-05-26 01:26:41 +0100414 CALL_HEAP_FUNCTION(obj->GetIsolate(),
415 obj->SetPrototype(*value, skip_hidden_prototypes), Object);
416}
417
418
419Handle<Object> PreventExtensions(Handle<JSObject> object) {
420 CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object);
Andrei Popescu402d9372010-02-26 13:31:12 +0000421}
422
423
Steve Blocka7e24c12009-10-30 11:49:00 +0000424Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
425 bool create_if_needed) {
Steve Block44f0eee2011-05-26 01:26:41 +0100426 Isolate* isolate = obj->GetIsolate();
Steve Blockd0582a62009-12-15 09:54:21 +0000427 Object* holder = obj->BypassGlobalProxy();
Steve Block44f0eee2011-05-26 01:26:41 +0100428 if (holder->IsUndefined()) return isolate->factory()->undefined_value();
429 obj = Handle<JSObject>(JSObject::cast(holder), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000430
431 if (obj->HasFastProperties()) {
432 // If the object has fast properties, check whether the first slot
433 // in the descriptor array matches the hidden symbol. Since the
434 // hidden symbols hash code is zero (and no other string has hash
435 // code zero) it will always occupy the first entry if present.
436 DescriptorArray* descriptors = obj->map()->instance_descriptors();
437 if ((descriptors->number_of_descriptors() > 0) &&
Steve Block44f0eee2011-05-26 01:26:41 +0100438 (descriptors->GetKey(0) == isolate->heap()->hidden_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 descriptors->IsProperty(0)) {
440 ASSERT(descriptors->GetType(0) == FIELD);
Steve Block44f0eee2011-05-26 01:26:41 +0100441 return Handle<Object>(obj->FastPropertyAt(descriptors->GetFieldIndex(0)),
442 isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 }
444 }
445
446 // Only attempt to find the hidden properties in the local object and not
447 // in the prototype chain. Note that HasLocalProperty() can cause a GC in
448 // the general case in the presence of interceptors.
Steve Blockd0582a62009-12-15 09:54:21 +0000449 if (!obj->HasHiddenPropertiesObject()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000450 // Hidden properties object not found. Allocate a new hidden properties
451 // object if requested. Otherwise return the undefined value.
452 if (create_if_needed) {
Steve Block44f0eee2011-05-26 01:26:41 +0100453 Handle<Object> hidden_obj =
454 isolate->factory()->NewJSObject(isolate->object_function());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000455
456 // Don't allow leakage of the hidden object through accessors
457 // on Object.prototype.
458 SetPrototype(Handle<JSObject>::cast(hidden_obj),
459 isolate->factory()->null_value());
Steve Block44f0eee2011-05-26 01:26:41 +0100460 CALL_HEAP_FUNCTION(isolate,
461 obj->SetHiddenPropertiesObject(*hidden_obj), Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000462 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100463 return isolate->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000464 }
465 }
Steve Block44f0eee2011-05-26 01:26:41 +0100466 return Handle<Object>(obj->GetHiddenPropertiesObject(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000467}
468
469
470Handle<Object> DeleteElement(Handle<JSObject> obj,
471 uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +0100472 CALL_HEAP_FUNCTION(obj->GetIsolate(),
473 obj->DeleteElement(index, JSObject::NORMAL_DELETION),
Steve Blocka7e24c12009-10-30 11:49:00 +0000474 Object);
475}
476
477
478Handle<Object> DeleteProperty(Handle<JSObject> obj,
479 Handle<String> prop) {
Steve Block44f0eee2011-05-26 01:26:41 +0100480 CALL_HEAP_FUNCTION(obj->GetIsolate(),
481 obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
Steve Blocka7e24c12009-10-30 11:49:00 +0000482 Object);
483}
484
485
486Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +0100487 Isolate* isolate = Isolate::Current();
488 CALL_HEAP_FUNCTION(
489 isolate,
490 isolate->heap()->LookupSingleCharacterStringFromCode(index), Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000491}
492
493
Steve Block6ded16b2010-05-10 14:33:55 +0100494Handle<String> SubString(Handle<String> str,
495 int start,
496 int end,
497 PretenureFlag pretenure) {
Steve Block44f0eee2011-05-26 01:26:41 +0100498 CALL_HEAP_FUNCTION(str->GetIsolate(),
499 str->SubString(start, end, pretenure), String);
Steve Blocka7e24c12009-10-30 11:49:00 +0000500}
501
502
503Handle<Object> SetElement(Handle<JSObject> object,
504 uint32_t index,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100505 Handle<Object> value,
506 StrictModeFlag strict_mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100507 if (object->HasExternalArrayElements()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000508 if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
509 bool has_exception;
510 Handle<Object> number = Execution::ToNumber(value, &has_exception);
511 if (has_exception) return Handle<Object>();
512 value = number;
513 }
514 }
Steve Block44f0eee2011-05-26 01:26:41 +0100515 CALL_HEAP_FUNCTION(object->GetIsolate(),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000516 object->SetElement(index, *value, strict_mode, true),
517 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000518}
519
520
Ben Murdoch086aeea2011-05-13 15:57:08 +0100521Handle<Object> SetOwnElement(Handle<JSObject> object,
522 uint32_t index,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100523 Handle<Object> value,
524 StrictModeFlag strict_mode) {
Ben Murdoch086aeea2011-05-13 15:57:08 +0100525 ASSERT(!object->HasExternalArrayElements());
Steve Block44f0eee2011-05-26 01:26:41 +0100526 CALL_HEAP_FUNCTION(object->GetIsolate(),
527 object->SetElement(index, *value, strict_mode, false),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100528 Object);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100529}
530
531
Steve Blocka7e24c12009-10-30 11:49:00 +0000532Handle<JSObject> Copy(Handle<JSObject> obj) {
Steve Block44f0eee2011-05-26 01:26:41 +0100533 Isolate* isolate = obj->GetIsolate();
534 CALL_HEAP_FUNCTION(isolate,
535 isolate->heap()->CopyJSObject(*obj), JSObject);
Steve Blocka7e24c12009-10-30 11:49:00 +0000536}
537
538
Leon Clarkef7060e22010-06-03 12:02:55 +0100539Handle<Object> SetAccessor(Handle<JSObject> obj, Handle<AccessorInfo> info) {
Steve Block44f0eee2011-05-26 01:26:41 +0100540 CALL_HEAP_FUNCTION(obj->GetIsolate(), obj->DefineAccessor(*info), Object);
Leon Clarkef7060e22010-06-03 12:02:55 +0100541}
542
543
Steve Blocka7e24c12009-10-30 11:49:00 +0000544// Wrappers for scripts are kept alive and cached in weak global
Ben Murdoch257744e2011-11-30 15:57:28 +0000545// handles referred from foreign objects held by the scripts as long as
Steve Blocka7e24c12009-10-30 11:49:00 +0000546// they are used. When they are not used anymore, the garbage
547// collector will call the weak callback on the global handle
548// associated with the wrapper and get rid of both the wrapper and the
549// handle.
550static void ClearWrapperCache(Persistent<v8::Value> handle, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000551 Handle<Object> cache = Utils::OpenHandle(*handle);
552 JSValue* wrapper = JSValue::cast(*cache);
Ben Murdoch257744e2011-11-30 15:57:28 +0000553 Foreign* foreign = Script::cast(wrapper->value())->wrapper();
554 ASSERT(foreign->address() == reinterpret_cast<Address>(cache.location()));
555 foreign->set_address(0);
Steve Block44f0eee2011-05-26 01:26:41 +0100556 Isolate* isolate = Isolate::Current();
557 isolate->global_handles()->Destroy(cache.location());
558 isolate->counters()->script_wrappers()->Decrement();
Steve Blocka7e24c12009-10-30 11:49:00 +0000559}
560
561
562Handle<JSValue> GetScriptWrapper(Handle<Script> script) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000563 if (script->wrapper()->address() != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000564 // Return the script wrapper directly from the cache.
565 return Handle<JSValue>(
Ben Murdoch257744e2011-11-30 15:57:28 +0000566 reinterpret_cast<JSValue**>(script->wrapper()->address()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000567 }
Steve Block44f0eee2011-05-26 01:26:41 +0100568 Isolate* isolate = Isolate::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000569 // Construct a new script wrapper.
Steve Block44f0eee2011-05-26 01:26:41 +0100570 isolate->counters()->script_wrappers()->Increment();
571 Handle<JSFunction> constructor = isolate->script_function();
Steve Blocka7e24c12009-10-30 11:49:00 +0000572 Handle<JSValue> result =
Steve Block44f0eee2011-05-26 01:26:41 +0100573 Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
Steve Blocka7e24c12009-10-30 11:49:00 +0000574 result->set_value(*script);
575
576 // Create a new weak global handle and use it to cache the wrapper
577 // for future use. The cache will automatically be cleared by the
578 // garbage collector when it is not used anymore.
Steve Block44f0eee2011-05-26 01:26:41 +0100579 Handle<Object> handle = isolate->global_handles()->Create(*result);
580 isolate->global_handles()->MakeWeak(handle.location(), NULL,
581 &ClearWrapperCache);
Ben Murdoch257744e2011-11-30 15:57:28 +0000582 script->wrapper()->set_address(reinterpret_cast<Address>(handle.location()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000583 return result;
584}
585
586
587// Init line_ends array with code positions of line ends inside script
588// source.
589void InitScriptLineEnds(Handle<Script> script) {
590 if (!script->line_ends()->IsUndefined()) return;
591
Steve Block44f0eee2011-05-26 01:26:41 +0100592 Isolate* isolate = script->GetIsolate();
593
Steve Blocka7e24c12009-10-30 11:49:00 +0000594 if (!script->source()->IsString()) {
595 ASSERT(script->source()->IsUndefined());
Steve Block44f0eee2011-05-26 01:26:41 +0100596 Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100597 script->set_line_ends(*empty);
Steve Blockd0582a62009-12-15 09:54:21 +0000598 ASSERT(script->line_ends()->IsFixedArray());
Steve Blocka7e24c12009-10-30 11:49:00 +0000599 return;
600 }
601
Steve Block44f0eee2011-05-26 01:26:41 +0100602 Handle<String> src(String::cast(script->source()), isolate);
Steve Block6ded16b2010-05-10 14:33:55 +0100603
604 Handle<FixedArray> array = CalculateLineEnds(src, true);
605
Steve Block44f0eee2011-05-26 01:26:41 +0100606 if (*array != isolate->heap()->empty_fixed_array()) {
607 array->set_map(isolate->heap()->fixed_cow_array_map());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800608 }
609
Steve Block6ded16b2010-05-10 14:33:55 +0100610 script->set_line_ends(*array);
611 ASSERT(script->line_ends()->IsFixedArray());
612}
613
614
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800615template <typename SourceChar>
Steve Block44f0eee2011-05-26 01:26:41 +0100616static void CalculateLineEnds(Isolate* isolate,
617 List<int>* line_ends,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800618 Vector<const SourceChar> src,
619 bool with_last_line) {
620 const int src_len = src.length();
Steve Block44f0eee2011-05-26 01:26:41 +0100621 StringSearch<char, SourceChar> search(isolate, CStrVector("\n"));
Steve Blocka7e24c12009-10-30 11:49:00 +0000622
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800623 // Find and record line ends.
Steve Blocka7e24c12009-10-30 11:49:00 +0000624 int position = 0;
625 while (position != -1 && position < src_len) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800626 position = search.Search(src, position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000627 if (position != -1) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800628 line_ends->Add(position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000629 position++;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800630 } else if (with_last_line) {
Steve Block6ded16b2010-05-10 14:33:55 +0100631 // Even if the last line misses a line end, it is counted.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800632 line_ends->Add(src_len);
633 return;
Steve Block6ded16b2010-05-10 14:33:55 +0100634 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000635 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800636}
Steve Blocka7e24c12009-10-30 11:49:00 +0000637
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800638
639Handle<FixedArray> CalculateLineEnds(Handle<String> src,
640 bool with_last_line) {
641 src = FlattenGetString(src);
642 // Rough estimate of line count based on a roughly estimated average
643 // length of (unpacked) code.
644 int line_count_estimate = src->length() >> 4;
645 List<int> line_ends(line_count_estimate);
Steve Block44f0eee2011-05-26 01:26:41 +0100646 Isolate* isolate = src->GetIsolate();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800647 {
648 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid.
649 // Dispatch on type of strings.
650 if (src->IsAsciiRepresentation()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100651 CalculateLineEnds(isolate,
652 &line_ends,
653 src->ToAsciiVector(),
654 with_last_line);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800655 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100656 CalculateLineEnds(isolate,
657 &line_ends,
658 src->ToUC16Vector(),
659 with_last_line);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800660 }
661 }
662 int line_count = line_ends.length();
Steve Block44f0eee2011-05-26 01:26:41 +0100663 Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800664 for (int i = 0; i < line_count; i++) {
665 array->set(i, Smi::FromInt(line_ends[i]));
Steve Blocka7e24c12009-10-30 11:49:00 +0000666 }
Steve Block6ded16b2010-05-10 14:33:55 +0100667 return array;
Steve Blocka7e24c12009-10-30 11:49:00 +0000668}
669
670
671// Convert code position into line number.
672int GetScriptLineNumber(Handle<Script> script, int code_pos) {
673 InitScriptLineEnds(script);
674 AssertNoAllocation no_allocation;
Andrei Popescu402d9372010-02-26 13:31:12 +0000675 FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
Steve Blockd0582a62009-12-15 09:54:21 +0000676 const int line_ends_len = line_ends_array->length();
Steve Blocka7e24c12009-10-30 11:49:00 +0000677
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800678 if (!line_ends_len) return -1;
Andrei Popescu402d9372010-02-26 13:31:12 +0000679
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800680 if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000681 return script->line_offset()->value();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800682 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000683
684 int left = 0;
685 int right = line_ends_len;
686 while (int half = (right - left) / 2) {
687 if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
688 right -= half;
689 } else {
690 left += half;
Steve Blocka7e24c12009-10-30 11:49:00 +0000691 }
692 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000693 return right + script->line_offset()->value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000694}
695
696
Steve Block6ded16b2010-05-10 14:33:55 +0100697int GetScriptLineNumberSafe(Handle<Script> script, int code_pos) {
698 AssertNoAllocation no_allocation;
699 if (!script->line_ends()->IsUndefined()) {
700 return GetScriptLineNumber(script, code_pos);
701 }
702 // Slow mode: we do not have line_ends. We have to iterate through source.
703 if (!script->source()->IsString()) {
704 return -1;
705 }
706 String* source = String::cast(script->source());
707 int line = 0;
708 int len = source->length();
709 for (int pos = 0; pos < len; pos++) {
710 if (pos == code_pos) {
711 break;
712 }
713 if (source->Get(pos) == '\n') {
714 line++;
715 }
716 }
717 return line;
718}
719
720
Steve Blocka7e24c12009-10-30 11:49:00 +0000721void CustomArguments::IterateInstance(ObjectVisitor* v) {
Steve Block6ded16b2010-05-10 14:33:55 +0100722 v->VisitPointers(values_, values_ + ARRAY_SIZE(values_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000723}
724
725
726// Compute the property keys from the interceptor.
727v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
728 Handle<JSObject> object) {
Steve Block44f0eee2011-05-26 01:26:41 +0100729 Isolate* isolate = receiver->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +0000730 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
Steve Block44f0eee2011-05-26 01:26:41 +0100731 CustomArguments args(isolate, interceptor->data(), *receiver, *object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000732 v8::AccessorInfo info(args.end());
733 v8::Handle<v8::Array> result;
734 if (!interceptor->enumerator()->IsUndefined()) {
735 v8::NamedPropertyEnumerator enum_fun =
736 v8::ToCData<v8::NamedPropertyEnumerator>(interceptor->enumerator());
Steve Block44f0eee2011-05-26 01:26:41 +0100737 LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
Steve Blocka7e24c12009-10-30 11:49:00 +0000738 {
739 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100740 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000741 result = enum_fun(info);
742 }
743 }
744 return result;
745}
746
747
748// Compute the element keys from the interceptor.
749v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
750 Handle<JSObject> object) {
Steve Block44f0eee2011-05-26 01:26:41 +0100751 Isolate* isolate = receiver->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +0000752 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
Steve Block44f0eee2011-05-26 01:26:41 +0100753 CustomArguments args(isolate, interceptor->data(), *receiver, *object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000754 v8::AccessorInfo info(args.end());
755 v8::Handle<v8::Array> result;
756 if (!interceptor->enumerator()->IsUndefined()) {
757 v8::IndexedPropertyEnumerator enum_fun =
758 v8::ToCData<v8::IndexedPropertyEnumerator>(interceptor->enumerator());
Steve Block44f0eee2011-05-26 01:26:41 +0100759 LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
Steve Blocka7e24c12009-10-30 11:49:00 +0000760 {
761 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100762 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000763 result = enum_fun(info);
764 }
765 }
766 return result;
767}
768
769
Ben Murdochf87a2032010-10-22 12:50:53 +0100770static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
771 int len = array->length();
772 for (int i = 0; i < len; i++) {
773 Object* e = array->get(i);
774 if (!(e->IsString() || e->IsNumber())) return false;
775 }
776 return true;
777}
778
779
Steve Blocka7e24c12009-10-30 11:49:00 +0000780Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
781 KeyCollectionType type) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100782 USE(ContainsOnlyValidKeys);
Steve Block44f0eee2011-05-26 01:26:41 +0100783 Isolate* isolate = object->GetIsolate();
784 Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
785 Handle<JSObject> arguments_boilerplate = Handle<JSObject>(
786 isolate->context()->global_context()->arguments_boilerplate(),
787 isolate);
788 Handle<JSFunction> arguments_function = Handle<JSFunction>(
789 JSFunction::cast(arguments_boilerplate->map()->constructor()),
790 isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000791
792 // Only collect keys if access is permitted.
793 for (Handle<Object> p = object;
Steve Block44f0eee2011-05-26 01:26:41 +0100794 *p != isolate->heap()->null_value();
795 p = Handle<Object>(p->GetPrototype(), isolate)) {
796 Handle<JSObject> current(JSObject::cast(*p), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000797
798 // Check access rights if required.
799 if (current->IsAccessCheckNeeded() &&
Steve Block44f0eee2011-05-26 01:26:41 +0100800 !isolate->MayNamedAccess(*current,
801 isolate->heap()->undefined_value(),
802 v8::ACCESS_KEYS)) {
803 isolate->ReportFailedAccessCheck(*current, v8::ACCESS_KEYS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000804 break;
805 }
806
807 // Compute the element keys.
808 Handle<FixedArray> element_keys =
Steve Block44f0eee2011-05-26 01:26:41 +0100809 isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
Steve Blocka7e24c12009-10-30 11:49:00 +0000810 current->GetEnumElementKeys(*element_keys);
811 content = UnionOfKeys(content, element_keys);
Ben Murdochf87a2032010-10-22 12:50:53 +0100812 ASSERT(ContainsOnlyValidKeys(content));
Steve Blocka7e24c12009-10-30 11:49:00 +0000813
814 // Add the element keys from the interceptor.
815 if (current->HasIndexedInterceptor()) {
816 v8::Handle<v8::Array> result =
817 GetKeysForIndexedInterceptor(object, current);
818 if (!result.IsEmpty())
819 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
Ben Murdochf87a2032010-10-22 12:50:53 +0100820 ASSERT(ContainsOnlyValidKeys(content));
Steve Blocka7e24c12009-10-30 11:49:00 +0000821 }
822
Steve Blockd0582a62009-12-15 09:54:21 +0000823 // We can cache the computed property keys if access checks are
824 // not needed and no interceptors are involved.
825 //
826 // We do not use the cache if the object has elements and
827 // therefore it does not make sense to cache the property names
828 // for arguments objects. Arguments objects will always have
829 // elements.
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100830 // Wrapped strings have elements, but don't have an elements
831 // array or dictionary. So the fast inline test for whether to
832 // use the cache says yes, so we should not create a cache.
Steve Blockd0582a62009-12-15 09:54:21 +0000833 bool cache_enum_keys =
834 ((current->map()->constructor() != *arguments_function) &&
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100835 !current->IsJSValue() &&
Steve Blockd0582a62009-12-15 09:54:21 +0000836 !current->IsAccessCheckNeeded() &&
837 !current->HasNamedInterceptor() &&
838 !current->HasIndexedInterceptor());
839 // Compute the property keys and cache them if possible.
840 content =
841 UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys));
Ben Murdochf87a2032010-10-22 12:50:53 +0100842 ASSERT(ContainsOnlyValidKeys(content));
Steve Blocka7e24c12009-10-30 11:49:00 +0000843
844 // Add the property keys from the interceptor.
845 if (current->HasNamedInterceptor()) {
846 v8::Handle<v8::Array> result =
847 GetKeysForNamedInterceptor(object, current);
848 if (!result.IsEmpty())
849 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
Ben Murdochf87a2032010-10-22 12:50:53 +0100850 ASSERT(ContainsOnlyValidKeys(content));
Steve Blocka7e24c12009-10-30 11:49:00 +0000851 }
852
853 // If we only want local properties we bail out after the first
854 // iteration.
855 if (type == LOCAL_ONLY)
856 break;
857 }
858 return content;
859}
860
861
862Handle<JSArray> GetKeysFor(Handle<JSObject> object) {
Steve Block44f0eee2011-05-26 01:26:41 +0100863 Isolate* isolate = object->GetIsolate();
864 isolate->counters()->for_in()->Increment();
Steve Blocka7e24c12009-10-30 11:49:00 +0000865 Handle<FixedArray> elements = GetKeysInFixedArrayFor(object,
866 INCLUDE_PROTOS);
Steve Block44f0eee2011-05-26 01:26:41 +0100867 return isolate->factory()->NewJSArrayWithElements(elements);
Steve Blocka7e24c12009-10-30 11:49:00 +0000868}
869
870
Steve Blockd0582a62009-12-15 09:54:21 +0000871Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
872 bool cache_result) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000873 int index = 0;
Steve Block44f0eee2011-05-26 01:26:41 +0100874 Isolate* isolate = object->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +0000875 if (object->HasFastProperties()) {
876 if (object->map()->instance_descriptors()->HasEnumCache()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100877 isolate->counters()->enum_cache_hits()->Increment();
Steve Blocka7e24c12009-10-30 11:49:00 +0000878 DescriptorArray* desc = object->map()->instance_descriptors();
Steve Block44f0eee2011-05-26 01:26:41 +0100879 return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache()),
880 isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000881 }
Steve Block44f0eee2011-05-26 01:26:41 +0100882 isolate->counters()->enum_cache_misses()->Increment();
Steve Blocka7e24c12009-10-30 11:49:00 +0000883 int num_enum = object->NumberOfEnumProperties();
Steve Block44f0eee2011-05-26 01:26:41 +0100884 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
885 Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
Steve Blocka7e24c12009-10-30 11:49:00 +0000886 Handle<DescriptorArray> descs =
Steve Block44f0eee2011-05-26 01:26:41 +0100887 Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000888 for (int i = 0; i < descs->number_of_descriptors(); i++) {
889 if (descs->IsProperty(i) && !descs->IsDontEnum(i)) {
890 (*storage)->set(index, descs->GetKey(i));
891 PropertyDetails details(descs->GetDetails(i));
892 (*sort_array)->set(index, Smi::FromInt(details.index()));
893 index++;
894 }
895 }
896 (*storage)->SortPairs(*sort_array, sort_array->length());
Steve Blockd0582a62009-12-15 09:54:21 +0000897 if (cache_result) {
898 Handle<FixedArray> bridge_storage =
Steve Block44f0eee2011-05-26 01:26:41 +0100899 isolate->factory()->NewFixedArray(
900 DescriptorArray::kEnumCacheBridgeLength);
Steve Blockd0582a62009-12-15 09:54:21 +0000901 DescriptorArray* desc = object->map()->instance_descriptors();
902 desc->SetEnumCache(*bridge_storage, *storage);
903 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000904 ASSERT(storage->length() == index);
905 return storage;
906 } else {
907 int num_enum = object->NumberOfEnumProperties();
Steve Block44f0eee2011-05-26 01:26:41 +0100908 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
909 Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
Steve Blocka7e24c12009-10-30 11:49:00 +0000910 object->property_dictionary()->CopyEnumKeysTo(*storage, *sort_array);
911 return storage;
912 }
913}
914
915
Leon Clarke4515c472010-02-03 11:58:03 +0000916bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
917 ClearExceptionFlag flag) {
918 return shared->is_compiled() || CompileLazyShared(shared, flag);
919}
920
921
922static bool CompileLazyHelper(CompilationInfo* info,
923 ClearExceptionFlag flag) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000924 // Compile the source information to a code object.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100925 ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
Steve Block44f0eee2011-05-26 01:26:41 +0100926 ASSERT(!info->isolate()->has_pending_exception());
Leon Clarke4515c472010-02-03 11:58:03 +0000927 bool result = Compiler::CompileLazy(info);
Steve Block44f0eee2011-05-26 01:26:41 +0100928 ASSERT(result != Isolate::Current()->has_pending_exception());
929 if (!result && flag == CLEAR_EXCEPTION) {
930 info->isolate()->clear_pending_exception();
931 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000932 return result;
933}
934
935
Leon Clarke4515c472010-02-03 11:58:03 +0000936bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
937 ClearExceptionFlag flag) {
Andrei Popescu31002712010-02-23 13:46:05 +0000938 CompilationInfo info(shared);
Leon Clarke4515c472010-02-03 11:58:03 +0000939 return CompileLazyHelper(&info, flag);
940}
941
942
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100943static bool CompileLazyFunction(Handle<JSFunction> function,
944 ClearExceptionFlag flag,
945 InLoopFlag in_loop_flag) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100946 bool result = true;
Iain Merrick75681382010-08-19 15:07:18 +0100947 if (function->shared()->is_compiled()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100948 function->ReplaceCode(function->shared()->code());
Iain Merrick75681382010-08-19 15:07:18 +0100949 function->shared()->set_code_age(0);
Iain Merrick75681382010-08-19 15:07:18 +0100950 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +0100951 CompilationInfo info(function);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100952 if (in_loop_flag == IN_LOOP) info.MarkAsInLoop();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100953 result = CompileLazyHelper(&info, flag);
Ben Murdochf87a2032010-10-22 12:50:53 +0100954 ASSERT(!result || function->is_compiled());
Iain Merrick75681382010-08-19 15:07:18 +0100955 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100956 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000957}
958
959
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100960bool CompileLazy(Handle<JSFunction> function,
961 ClearExceptionFlag flag) {
962 return CompileLazyFunction(function, flag, NOT_IN_LOOP);
963}
964
965
Leon Clarke4515c472010-02-03 11:58:03 +0000966bool CompileLazyInLoop(Handle<JSFunction> function,
Leon Clarke4515c472010-02-03 11:58:03 +0000967 ClearExceptionFlag flag) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100968 return CompileLazyFunction(function, flag, IN_LOOP);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100969}
970
971
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100972bool CompileOptimized(Handle<JSFunction> function,
973 int osr_ast_id,
974 ClearExceptionFlag flag) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100975 CompilationInfo info(function);
976 info.SetOptimizing(osr_ast_id);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100977 return CompileLazyHelper(&info, flag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000978}
979
Steve Blocka7e24c12009-10-30 11:49:00 +0000980} } // namespace v8::internal