blob: 8c6439b227adbb2336459c368b79f21e7d005ed3 [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,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000425 JSObject::HiddenPropertiesFlag flag) {
426 CALL_HEAP_FUNCTION(obj->GetIsolate(),
427 obj->GetHiddenProperties(flag),
428 Object);
429}
Steve Blocka7e24c12009-10-30 11:49:00 +0000430
Steve Blocka7e24c12009-10-30 11:49:00 +0000431
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000432int GetIdentityHash(Handle<JSObject> obj) {
433 CALL_AND_RETRY(obj->GetIsolate(),
434 obj->GetIdentityHash(JSObject::ALLOW_CREATION),
435 return Smi::cast(__object__)->value(),
436 return 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000437}
438
439
440Handle<Object> DeleteElement(Handle<JSObject> obj,
441 uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +0100442 CALL_HEAP_FUNCTION(obj->GetIsolate(),
443 obj->DeleteElement(index, JSObject::NORMAL_DELETION),
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 Object);
445}
446
447
448Handle<Object> DeleteProperty(Handle<JSObject> obj,
449 Handle<String> prop) {
Steve Block44f0eee2011-05-26 01:26:41 +0100450 CALL_HEAP_FUNCTION(obj->GetIsolate(),
451 obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 Object);
453}
454
455
456Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +0100457 Isolate* isolate = Isolate::Current();
458 CALL_HEAP_FUNCTION(
459 isolate,
460 isolate->heap()->LookupSingleCharacterStringFromCode(index), Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000461}
462
463
Steve Block6ded16b2010-05-10 14:33:55 +0100464Handle<String> SubString(Handle<String> str,
465 int start,
466 int end,
467 PretenureFlag pretenure) {
Steve Block44f0eee2011-05-26 01:26:41 +0100468 CALL_HEAP_FUNCTION(str->GetIsolate(),
469 str->SubString(start, end, pretenure), String);
Steve Blocka7e24c12009-10-30 11:49:00 +0000470}
471
472
473Handle<Object> SetElement(Handle<JSObject> object,
474 uint32_t index,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100475 Handle<Object> value,
476 StrictModeFlag strict_mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100477 if (object->HasExternalArrayElements()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000478 if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
479 bool has_exception;
480 Handle<Object> number = Execution::ToNumber(value, &has_exception);
481 if (has_exception) return Handle<Object>();
482 value = number;
483 }
484 }
Steve Block44f0eee2011-05-26 01:26:41 +0100485 CALL_HEAP_FUNCTION(object->GetIsolate(),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000486 object->SetElement(index, *value, strict_mode, true),
487 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000488}
489
490
Ben Murdoch086aeea2011-05-13 15:57:08 +0100491Handle<Object> SetOwnElement(Handle<JSObject> object,
492 uint32_t index,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100493 Handle<Object> value,
494 StrictModeFlag strict_mode) {
Ben Murdoch086aeea2011-05-13 15:57:08 +0100495 ASSERT(!object->HasExternalArrayElements());
Steve Block44f0eee2011-05-26 01:26:41 +0100496 CALL_HEAP_FUNCTION(object->GetIsolate(),
497 object->SetElement(index, *value, strict_mode, false),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100498 Object);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100499}
500
501
Steve Blocka7e24c12009-10-30 11:49:00 +0000502Handle<JSObject> Copy(Handle<JSObject> obj) {
Steve Block44f0eee2011-05-26 01:26:41 +0100503 Isolate* isolate = obj->GetIsolate();
504 CALL_HEAP_FUNCTION(isolate,
505 isolate->heap()->CopyJSObject(*obj), JSObject);
Steve Blocka7e24c12009-10-30 11:49:00 +0000506}
507
508
Leon Clarkef7060e22010-06-03 12:02:55 +0100509Handle<Object> SetAccessor(Handle<JSObject> obj, Handle<AccessorInfo> info) {
Steve Block44f0eee2011-05-26 01:26:41 +0100510 CALL_HEAP_FUNCTION(obj->GetIsolate(), obj->DefineAccessor(*info), Object);
Leon Clarkef7060e22010-06-03 12:02:55 +0100511}
512
513
Steve Blocka7e24c12009-10-30 11:49:00 +0000514// Wrappers for scripts are kept alive and cached in weak global
Ben Murdoch257744e2011-11-30 15:57:28 +0000515// handles referred from foreign objects held by the scripts as long as
Steve Blocka7e24c12009-10-30 11:49:00 +0000516// they are used. When they are not used anymore, the garbage
517// collector will call the weak callback on the global handle
518// associated with the wrapper and get rid of both the wrapper and the
519// handle.
520static void ClearWrapperCache(Persistent<v8::Value> handle, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 Handle<Object> cache = Utils::OpenHandle(*handle);
522 JSValue* wrapper = JSValue::cast(*cache);
Ben Murdoch257744e2011-11-30 15:57:28 +0000523 Foreign* foreign = Script::cast(wrapper->value())->wrapper();
524 ASSERT(foreign->address() == reinterpret_cast<Address>(cache.location()));
525 foreign->set_address(0);
Steve Block44f0eee2011-05-26 01:26:41 +0100526 Isolate* isolate = Isolate::Current();
527 isolate->global_handles()->Destroy(cache.location());
528 isolate->counters()->script_wrappers()->Decrement();
Steve Blocka7e24c12009-10-30 11:49:00 +0000529}
530
531
532Handle<JSValue> GetScriptWrapper(Handle<Script> script) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000533 if (script->wrapper()->address() != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000534 // Return the script wrapper directly from the cache.
535 return Handle<JSValue>(
Ben Murdoch257744e2011-11-30 15:57:28 +0000536 reinterpret_cast<JSValue**>(script->wrapper()->address()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000537 }
Steve Block44f0eee2011-05-26 01:26:41 +0100538 Isolate* isolate = Isolate::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000539 // Construct a new script wrapper.
Steve Block44f0eee2011-05-26 01:26:41 +0100540 isolate->counters()->script_wrappers()->Increment();
541 Handle<JSFunction> constructor = isolate->script_function();
Steve Blocka7e24c12009-10-30 11:49:00 +0000542 Handle<JSValue> result =
Steve Block44f0eee2011-05-26 01:26:41 +0100543 Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
Steve Blocka7e24c12009-10-30 11:49:00 +0000544 result->set_value(*script);
545
546 // Create a new weak global handle and use it to cache the wrapper
547 // for future use. The cache will automatically be cleared by the
548 // garbage collector when it is not used anymore.
Steve Block44f0eee2011-05-26 01:26:41 +0100549 Handle<Object> handle = isolate->global_handles()->Create(*result);
550 isolate->global_handles()->MakeWeak(handle.location(), NULL,
551 &ClearWrapperCache);
Ben Murdoch257744e2011-11-30 15:57:28 +0000552 script->wrapper()->set_address(reinterpret_cast<Address>(handle.location()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000553 return result;
554}
555
556
557// Init line_ends array with code positions of line ends inside script
558// source.
559void InitScriptLineEnds(Handle<Script> script) {
560 if (!script->line_ends()->IsUndefined()) return;
561
Steve Block44f0eee2011-05-26 01:26:41 +0100562 Isolate* isolate = script->GetIsolate();
563
Steve Blocka7e24c12009-10-30 11:49:00 +0000564 if (!script->source()->IsString()) {
565 ASSERT(script->source()->IsUndefined());
Steve Block44f0eee2011-05-26 01:26:41 +0100566 Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100567 script->set_line_ends(*empty);
Steve Blockd0582a62009-12-15 09:54:21 +0000568 ASSERT(script->line_ends()->IsFixedArray());
Steve Blocka7e24c12009-10-30 11:49:00 +0000569 return;
570 }
571
Steve Block44f0eee2011-05-26 01:26:41 +0100572 Handle<String> src(String::cast(script->source()), isolate);
Steve Block6ded16b2010-05-10 14:33:55 +0100573
574 Handle<FixedArray> array = CalculateLineEnds(src, true);
575
Steve Block44f0eee2011-05-26 01:26:41 +0100576 if (*array != isolate->heap()->empty_fixed_array()) {
577 array->set_map(isolate->heap()->fixed_cow_array_map());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800578 }
579
Steve Block6ded16b2010-05-10 14:33:55 +0100580 script->set_line_ends(*array);
581 ASSERT(script->line_ends()->IsFixedArray());
582}
583
584
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800585template <typename SourceChar>
Steve Block44f0eee2011-05-26 01:26:41 +0100586static void CalculateLineEnds(Isolate* isolate,
587 List<int>* line_ends,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800588 Vector<const SourceChar> src,
589 bool with_last_line) {
590 const int src_len = src.length();
Steve Block44f0eee2011-05-26 01:26:41 +0100591 StringSearch<char, SourceChar> search(isolate, CStrVector("\n"));
Steve Blocka7e24c12009-10-30 11:49:00 +0000592
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800593 // Find and record line ends.
Steve Blocka7e24c12009-10-30 11:49:00 +0000594 int position = 0;
595 while (position != -1 && position < src_len) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800596 position = search.Search(src, position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000597 if (position != -1) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800598 line_ends->Add(position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000599 position++;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800600 } else if (with_last_line) {
Steve Block6ded16b2010-05-10 14:33:55 +0100601 // Even if the last line misses a line end, it is counted.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800602 line_ends->Add(src_len);
603 return;
Steve Block6ded16b2010-05-10 14:33:55 +0100604 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000605 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800606}
Steve Blocka7e24c12009-10-30 11:49:00 +0000607
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800608
609Handle<FixedArray> CalculateLineEnds(Handle<String> src,
610 bool with_last_line) {
611 src = FlattenGetString(src);
612 // Rough estimate of line count based on a roughly estimated average
613 // length of (unpacked) code.
614 int line_count_estimate = src->length() >> 4;
615 List<int> line_ends(line_count_estimate);
Steve Block44f0eee2011-05-26 01:26:41 +0100616 Isolate* isolate = src->GetIsolate();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800617 {
618 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid.
619 // Dispatch on type of strings.
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000620 String::FlatContent content = src->GetFlatContent();
621 ASSERT(content.IsFlat());
622 if (content.IsAscii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100623 CalculateLineEnds(isolate,
624 &line_ends,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000625 content.ToAsciiVector(),
Steve Block44f0eee2011-05-26 01:26:41 +0100626 with_last_line);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800627 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100628 CalculateLineEnds(isolate,
629 &line_ends,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000630 content.ToUC16Vector(),
Steve Block44f0eee2011-05-26 01:26:41 +0100631 with_last_line);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800632 }
633 }
634 int line_count = line_ends.length();
Steve Block44f0eee2011-05-26 01:26:41 +0100635 Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800636 for (int i = 0; i < line_count; i++) {
637 array->set(i, Smi::FromInt(line_ends[i]));
Steve Blocka7e24c12009-10-30 11:49:00 +0000638 }
Steve Block6ded16b2010-05-10 14:33:55 +0100639 return array;
Steve Blocka7e24c12009-10-30 11:49:00 +0000640}
641
642
643// Convert code position into line number.
644int GetScriptLineNumber(Handle<Script> script, int code_pos) {
645 InitScriptLineEnds(script);
646 AssertNoAllocation no_allocation;
Andrei Popescu402d9372010-02-26 13:31:12 +0000647 FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
Steve Blockd0582a62009-12-15 09:54:21 +0000648 const int line_ends_len = line_ends_array->length();
Steve Blocka7e24c12009-10-30 11:49:00 +0000649
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800650 if (!line_ends_len) return -1;
Andrei Popescu402d9372010-02-26 13:31:12 +0000651
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800652 if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000653 return script->line_offset()->value();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800654 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000655
656 int left = 0;
657 int right = line_ends_len;
658 while (int half = (right - left) / 2) {
659 if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
660 right -= half;
661 } else {
662 left += half;
Steve Blocka7e24c12009-10-30 11:49:00 +0000663 }
664 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000665 return right + script->line_offset()->value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000666}
667
668
Steve Block6ded16b2010-05-10 14:33:55 +0100669int GetScriptLineNumberSafe(Handle<Script> script, int code_pos) {
670 AssertNoAllocation no_allocation;
671 if (!script->line_ends()->IsUndefined()) {
672 return GetScriptLineNumber(script, code_pos);
673 }
674 // Slow mode: we do not have line_ends. We have to iterate through source.
675 if (!script->source()->IsString()) {
676 return -1;
677 }
678 String* source = String::cast(script->source());
679 int line = 0;
680 int len = source->length();
681 for (int pos = 0; pos < len; pos++) {
682 if (pos == code_pos) {
683 break;
684 }
685 if (source->Get(pos) == '\n') {
686 line++;
687 }
688 }
689 return line;
690}
691
692
Steve Blocka7e24c12009-10-30 11:49:00 +0000693void CustomArguments::IterateInstance(ObjectVisitor* v) {
Steve Block6ded16b2010-05-10 14:33:55 +0100694 v->VisitPointers(values_, values_ + ARRAY_SIZE(values_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000695}
696
697
698// Compute the property keys from the interceptor.
699v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
700 Handle<JSObject> object) {
Steve Block44f0eee2011-05-26 01:26:41 +0100701 Isolate* isolate = receiver->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +0000702 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
Steve Block44f0eee2011-05-26 01:26:41 +0100703 CustomArguments args(isolate, interceptor->data(), *receiver, *object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000704 v8::AccessorInfo info(args.end());
705 v8::Handle<v8::Array> result;
706 if (!interceptor->enumerator()->IsUndefined()) {
707 v8::NamedPropertyEnumerator enum_fun =
708 v8::ToCData<v8::NamedPropertyEnumerator>(interceptor->enumerator());
Steve Block44f0eee2011-05-26 01:26:41 +0100709 LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
Steve Blocka7e24c12009-10-30 11:49:00 +0000710 {
711 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100712 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000713 result = enum_fun(info);
714 }
715 }
716 return result;
717}
718
719
720// Compute the element keys from the interceptor.
721v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
722 Handle<JSObject> object) {
Steve Block44f0eee2011-05-26 01:26:41 +0100723 Isolate* isolate = receiver->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +0000724 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
Steve Block44f0eee2011-05-26 01:26:41 +0100725 CustomArguments args(isolate, interceptor->data(), *receiver, *object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000726 v8::AccessorInfo info(args.end());
727 v8::Handle<v8::Array> result;
728 if (!interceptor->enumerator()->IsUndefined()) {
729 v8::IndexedPropertyEnumerator enum_fun =
730 v8::ToCData<v8::IndexedPropertyEnumerator>(interceptor->enumerator());
Steve Block44f0eee2011-05-26 01:26:41 +0100731 LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
Steve Blocka7e24c12009-10-30 11:49:00 +0000732 {
733 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100734 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000735 result = enum_fun(info);
736 }
737 }
738 return result;
739}
740
741
Ben Murdochf87a2032010-10-22 12:50:53 +0100742static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
743 int len = array->length();
744 for (int i = 0; i < len; i++) {
745 Object* e = array->get(i);
746 if (!(e->IsString() || e->IsNumber())) return false;
747 }
748 return true;
749}
750
751
Steve Blocka7e24c12009-10-30 11:49:00 +0000752Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
753 KeyCollectionType type) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100754 USE(ContainsOnlyValidKeys);
Steve Block44f0eee2011-05-26 01:26:41 +0100755 Isolate* isolate = object->GetIsolate();
756 Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
757 Handle<JSObject> arguments_boilerplate = Handle<JSObject>(
758 isolate->context()->global_context()->arguments_boilerplate(),
759 isolate);
760 Handle<JSFunction> arguments_function = Handle<JSFunction>(
761 JSFunction::cast(arguments_boilerplate->map()->constructor()),
762 isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000763
764 // Only collect keys if access is permitted.
765 for (Handle<Object> p = object;
Steve Block44f0eee2011-05-26 01:26:41 +0100766 *p != isolate->heap()->null_value();
767 p = Handle<Object>(p->GetPrototype(), isolate)) {
768 Handle<JSObject> current(JSObject::cast(*p), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000769
770 // Check access rights if required.
771 if (current->IsAccessCheckNeeded() &&
Steve Block44f0eee2011-05-26 01:26:41 +0100772 !isolate->MayNamedAccess(*current,
773 isolate->heap()->undefined_value(),
774 v8::ACCESS_KEYS)) {
775 isolate->ReportFailedAccessCheck(*current, v8::ACCESS_KEYS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000776 break;
777 }
778
779 // Compute the element keys.
780 Handle<FixedArray> element_keys =
Steve Block44f0eee2011-05-26 01:26:41 +0100781 isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
Steve Blocka7e24c12009-10-30 11:49:00 +0000782 current->GetEnumElementKeys(*element_keys);
783 content = UnionOfKeys(content, element_keys);
Ben Murdochf87a2032010-10-22 12:50:53 +0100784 ASSERT(ContainsOnlyValidKeys(content));
Steve Blocka7e24c12009-10-30 11:49:00 +0000785
786 // Add the element keys from the interceptor.
787 if (current->HasIndexedInterceptor()) {
788 v8::Handle<v8::Array> result =
789 GetKeysForIndexedInterceptor(object, current);
790 if (!result.IsEmpty())
791 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
Ben Murdochf87a2032010-10-22 12:50:53 +0100792 ASSERT(ContainsOnlyValidKeys(content));
Steve Blocka7e24c12009-10-30 11:49:00 +0000793 }
794
Steve Blockd0582a62009-12-15 09:54:21 +0000795 // We can cache the computed property keys if access checks are
796 // not needed and no interceptors are involved.
797 //
798 // We do not use the cache if the object has elements and
799 // therefore it does not make sense to cache the property names
800 // for arguments objects. Arguments objects will always have
801 // elements.
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100802 // Wrapped strings have elements, but don't have an elements
803 // array or dictionary. So the fast inline test for whether to
804 // use the cache says yes, so we should not create a cache.
Steve Blockd0582a62009-12-15 09:54:21 +0000805 bool cache_enum_keys =
806 ((current->map()->constructor() != *arguments_function) &&
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100807 !current->IsJSValue() &&
Steve Blockd0582a62009-12-15 09:54:21 +0000808 !current->IsAccessCheckNeeded() &&
809 !current->HasNamedInterceptor() &&
810 !current->HasIndexedInterceptor());
811 // Compute the property keys and cache them if possible.
812 content =
813 UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys));
Ben Murdochf87a2032010-10-22 12:50:53 +0100814 ASSERT(ContainsOnlyValidKeys(content));
Steve Blocka7e24c12009-10-30 11:49:00 +0000815
816 // Add the property keys from the interceptor.
817 if (current->HasNamedInterceptor()) {
818 v8::Handle<v8::Array> result =
819 GetKeysForNamedInterceptor(object, current);
820 if (!result.IsEmpty())
821 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
Ben Murdochf87a2032010-10-22 12:50:53 +0100822 ASSERT(ContainsOnlyValidKeys(content));
Steve Blocka7e24c12009-10-30 11:49:00 +0000823 }
824
825 // If we only want local properties we bail out after the first
826 // iteration.
827 if (type == LOCAL_ONLY)
828 break;
829 }
830 return content;
831}
832
833
834Handle<JSArray> GetKeysFor(Handle<JSObject> object) {
Steve Block44f0eee2011-05-26 01:26:41 +0100835 Isolate* isolate = object->GetIsolate();
836 isolate->counters()->for_in()->Increment();
Steve Blocka7e24c12009-10-30 11:49:00 +0000837 Handle<FixedArray> elements = GetKeysInFixedArrayFor(object,
838 INCLUDE_PROTOS);
Steve Block44f0eee2011-05-26 01:26:41 +0100839 return isolate->factory()->NewJSArrayWithElements(elements);
Steve Blocka7e24c12009-10-30 11:49:00 +0000840}
841
842
Steve Blockd0582a62009-12-15 09:54:21 +0000843Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
844 bool cache_result) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000845 int index = 0;
Steve Block44f0eee2011-05-26 01:26:41 +0100846 Isolate* isolate = object->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +0000847 if (object->HasFastProperties()) {
848 if (object->map()->instance_descriptors()->HasEnumCache()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100849 isolate->counters()->enum_cache_hits()->Increment();
Steve Blocka7e24c12009-10-30 11:49:00 +0000850 DescriptorArray* desc = object->map()->instance_descriptors();
Steve Block44f0eee2011-05-26 01:26:41 +0100851 return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache()),
852 isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000853 }
Steve Block44f0eee2011-05-26 01:26:41 +0100854 isolate->counters()->enum_cache_misses()->Increment();
Steve Blocka7e24c12009-10-30 11:49:00 +0000855 int num_enum = object->NumberOfEnumProperties();
Steve Block44f0eee2011-05-26 01:26:41 +0100856 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
857 Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
Steve Blocka7e24c12009-10-30 11:49:00 +0000858 Handle<DescriptorArray> descs =
Steve Block44f0eee2011-05-26 01:26:41 +0100859 Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000860 for (int i = 0; i < descs->number_of_descriptors(); i++) {
861 if (descs->IsProperty(i) && !descs->IsDontEnum(i)) {
862 (*storage)->set(index, descs->GetKey(i));
863 PropertyDetails details(descs->GetDetails(i));
864 (*sort_array)->set(index, Smi::FromInt(details.index()));
865 index++;
866 }
867 }
868 (*storage)->SortPairs(*sort_array, sort_array->length());
Steve Blockd0582a62009-12-15 09:54:21 +0000869 if (cache_result) {
870 Handle<FixedArray> bridge_storage =
Steve Block44f0eee2011-05-26 01:26:41 +0100871 isolate->factory()->NewFixedArray(
872 DescriptorArray::kEnumCacheBridgeLength);
Steve Blockd0582a62009-12-15 09:54:21 +0000873 DescriptorArray* desc = object->map()->instance_descriptors();
874 desc->SetEnumCache(*bridge_storage, *storage);
875 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000876 ASSERT(storage->length() == index);
877 return storage;
878 } else {
879 int num_enum = object->NumberOfEnumProperties();
Steve Block44f0eee2011-05-26 01:26:41 +0100880 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
881 Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
Steve Blocka7e24c12009-10-30 11:49:00 +0000882 object->property_dictionary()->CopyEnumKeysTo(*storage, *sort_array);
883 return storage;
884 }
885}
886
887
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000888Handle<ObjectHashTable> PutIntoObjectHashTable(Handle<ObjectHashTable> table,
889 Handle<JSObject> key,
890 Handle<Object> value) {
891 CALL_HEAP_FUNCTION(table->GetIsolate(),
892 table->Put(*key, *value),
893 ObjectHashTable);
894}
895
896
Leon Clarke4515c472010-02-03 11:58:03 +0000897bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
898 ClearExceptionFlag flag) {
899 return shared->is_compiled() || CompileLazyShared(shared, flag);
900}
901
902
903static bool CompileLazyHelper(CompilationInfo* info,
904 ClearExceptionFlag flag) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000905 // Compile the source information to a code object.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100906 ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
Steve Block44f0eee2011-05-26 01:26:41 +0100907 ASSERT(!info->isolate()->has_pending_exception());
Leon Clarke4515c472010-02-03 11:58:03 +0000908 bool result = Compiler::CompileLazy(info);
Steve Block44f0eee2011-05-26 01:26:41 +0100909 ASSERT(result != Isolate::Current()->has_pending_exception());
910 if (!result && flag == CLEAR_EXCEPTION) {
911 info->isolate()->clear_pending_exception();
912 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000913 return result;
914}
915
916
Leon Clarke4515c472010-02-03 11:58:03 +0000917bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
918 ClearExceptionFlag flag) {
Andrei Popescu31002712010-02-23 13:46:05 +0000919 CompilationInfo info(shared);
Leon Clarke4515c472010-02-03 11:58:03 +0000920 return CompileLazyHelper(&info, flag);
921}
922
923
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100924static bool CompileLazyFunction(Handle<JSFunction> function,
925 ClearExceptionFlag flag,
926 InLoopFlag in_loop_flag) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100927 bool result = true;
Iain Merrick75681382010-08-19 15:07:18 +0100928 if (function->shared()->is_compiled()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100929 function->ReplaceCode(function->shared()->code());
Iain Merrick75681382010-08-19 15:07:18 +0100930 function->shared()->set_code_age(0);
Iain Merrick75681382010-08-19 15:07:18 +0100931 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +0100932 CompilationInfo info(function);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100933 if (in_loop_flag == IN_LOOP) info.MarkAsInLoop();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100934 result = CompileLazyHelper(&info, flag);
Ben Murdochf87a2032010-10-22 12:50:53 +0100935 ASSERT(!result || function->is_compiled());
Iain Merrick75681382010-08-19 15:07:18 +0100936 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100937 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000938}
939
940
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100941bool CompileLazy(Handle<JSFunction> function,
942 ClearExceptionFlag flag) {
943 return CompileLazyFunction(function, flag, NOT_IN_LOOP);
944}
945
946
Leon Clarke4515c472010-02-03 11:58:03 +0000947bool CompileLazyInLoop(Handle<JSFunction> function,
Leon Clarke4515c472010-02-03 11:58:03 +0000948 ClearExceptionFlag flag) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100949 return CompileLazyFunction(function, flag, IN_LOOP);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100950}
951
952
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100953bool CompileOptimized(Handle<JSFunction> function,
954 int osr_ast_id,
955 ClearExceptionFlag flag) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100956 CompilationInfo info(function);
957 info.SetOptimizing(osr_ast_id);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100958 return CompileLazyHelper(&info, flag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000959}
960
Steve Blocka7e24c12009-10-30 11:49:00 +0000961} } // namespace v8::internal