1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
1 |
// Copyright 2012 the V8 project authors. All rights reserved.
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
2 |
// 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" |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
40 |
#include "string-search.h" |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
41 |
#include "stub-cache.h" |
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
42 |
#include "vm-state-inl.h" |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
43 |
|
44 |
namespace v8 { |
|
45 |
namespace internal { |
|
46 |
||
47 |
||
48 |
int HandleScope::NumberOfHandles() { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
49 |
Isolate* isolate = Isolate::Current(); |
50 |
HandleScopeImplementer* impl = isolate->handle_scope_implementer(); |
|
51 |
int n = impl->blocks()->length(); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
52 |
if (n == 0) return 0; |
53 |
return ((n - 1) * kHandleBlockSize) + static_cast<int>( |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
54 |
(isolate->handle_scope_data()->next - impl->blocks()->last())); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
55 |
}
|
56 |
||
57 |
||
58 |
Object** HandleScope::Extend() { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
59 |
Isolate* isolate = Isolate::Current(); |
60 |
v8::ImplementationUtilities::HandleScopeData* current = |
|
61 |
isolate->handle_scope_data(); |
|
62 |
||
63 |
Object** result = current->next; |
|
64 |
||
65 |
ASSERT(result == current->limit); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
66 |
// Make sure there's at least one scope on the stack and that the
|
67 |
// top of the scope stack isn't a barrier.
|
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
68 |
if (current->level == 0) { |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
69 |
Utils::ReportApiFailure("v8::HandleScope::CreateHandle()", |
70 |
"Cannot create a handle without a HandleScope"); |
|
71 |
return NULL; |
|
72 |
}
|
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
73 |
HandleScopeImplementer* impl = isolate->handle_scope_implementer(); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
74 |
// 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]; |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
78 |
if (current->limit != limit) { |
79 |
current->limit = limit; |
|
80 |
ASSERT(limit - current->next < kHandleBlockSize); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
81 |
}
|
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.
|
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
86 |
if (result == current->limit) { |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
87 |
// 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); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
92 |
current->limit = &result[kHandleBlockSize]; |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
93 |
}
|
94 |
||
95 |
return result; |
|
96 |
}
|
|
97 |
||
98 |
||
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
99 |
void 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); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
104 |
}
|
105 |
||
106 |
||
107 |
void HandleScope::ZapRange(Object** start, Object** end) { |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
108 |
ASSERT(end - start <= kHandleBlockSize); |
109 |
for (Object** p = start; p != end; p++) { |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
110 |
*reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue; |
111 |
}
|
|
112 |
}
|
|
113 |
||
114 |
||
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
115 |
Address HandleScope::current_level_address() { |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
116 |
return reinterpret_cast<Address>( |
117 |
&Isolate::Current()->handle_scope_data()->level); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
118 |
}
|
119 |
||
120 |
||
121 |
Address HandleScope::current_next_address() { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
122 |
return reinterpret_cast<Address>( |
123 |
&Isolate::Current()->handle_scope_data()->next); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
124 |
}
|
125 |
||
126 |
||
127 |
Address HandleScope::current_limit_address() { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
128 |
return reinterpret_cast<Address>( |
129 |
&Isolate::Current()->handle_scope_data()->limit); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
130 |
}
|
131 |
||
132 |
||
133 |
Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content, |
|
134 |
Handle<JSArray> array) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
135 |
CALL_HEAP_FUNCTION(content->GetIsolate(), |
136 |
content->AddKeysFromJSArray(*array), FixedArray); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
137 |
}
|
138 |
||
139 |
||
140 |
Handle<FixedArray> UnionOfKeys(Handle<FixedArray> first, |
|
141 |
Handle<FixedArray> second) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
142 |
CALL_HEAP_FUNCTION(first->GetIsolate(), |
143 |
first->UnionOfKeys(*second), FixedArray); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
144 |
}
|
145 |
||
146 |
||
147 |
Handle<JSGlobalProxy> ReinitializeJSGlobalProxy( |
|
148 |
Handle<JSFunction> constructor, |
|
149 |
Handle<JSGlobalProxy> global) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
150 |
CALL_HEAP_FUNCTION( |
151 |
constructor->GetIsolate(), |
|
152 |
constructor->GetHeap()->ReinitializeJSGlobalProxy(*constructor, *global), |
|
153 |
JSGlobalProxy); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
154 |
}
|
155 |
||
156 |
||
157 |
void SetExpectedNofProperties(Handle<JSFunction> func, int nof) { |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
158 |
// If objects constructed from this function exist then changing
|
159 |
// 'estimated_nof_properties' is dangerous since the previous value might
|
|
160 |
// 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 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
165 |
func->shared()->set_expected_nof_properties(nof); |
166 |
if (func->has_initial_map()) { |
|
167 |
Handle<Map> new_initial_map = |
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
168 |
func->GetIsolate()->factory()->CopyMap( |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
169 |
Handle<Map>(func->initial_map())); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
170 |
new_initial_map->set_unused_property_fields(nof); |
171 |
func->set_initial_map(*new_initial_map); |
|
172 |
}
|
|
173 |
}
|
|
174 |
||
175 |
||
176 |
void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
177 |
CALL_HEAP_FUNCTION_VOID(func->GetIsolate(), |
178 |
func->SetPrototype(*value)); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
179 |
}
|
180 |
||
181 |
||
182 |
static int ExpectedNofPropertiesFromEstimate(int estimate) { |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
183 |
// 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.
|
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
193 |
if (FLAG_clever_optimizations) { |
194 |
return estimate + 8; |
|
195 |
} else { |
|
196 |
return estimate + 3; |
|
197 |
}
|
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
198 |
}
|
199 |
||
200 |
||
201 |
void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared, |
|
202 |
int estimate) { |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
203 |
// See the comment in SetExpectedNofProperties.
|
204 |
if (shared->live_objects_may_exist()) return; |
|
205 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
206 |
shared->set_expected_nof_properties( |
207 |
ExpectedNofPropertiesFromEstimate(estimate)); |
|
208 |
}
|
|
209 |
||
210 |
||
211 |
void FlattenString(Handle<String> string) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
212 |
CALL_HEAP_FUNCTION_VOID(string->GetIsolate(), string->TryFlatten()); |
1.1.5
by Jérémy Lal
Import upstream version 0.1.101 |
213 |
}
|
214 |
||
215 |
||
216 |
Handle<String> FlattenGetString(Handle<String> string) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
217 |
CALL_HEAP_FUNCTION(string->GetIsolate(), string->TryFlatten(), String); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
218 |
}
|
219 |
||
220 |
||
221 |
Handle<Object> SetPrototype(Handle<JSFunction> function, |
|
222 |
Handle<Object> prototype) { |
|
1.1.2
by Jérémy Lal
Import upstream version 0.1.95 |
223 |
ASSERT(function->should_have_prototype()); |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
224 |
CALL_HEAP_FUNCTION(function->GetIsolate(), |
225 |
Accessors::FunctionSetPrototype(*function, |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
226 |
*prototype, |
227 |
NULL), |
|
228 |
Object); |
|
229 |
}
|
|
230 |
||
231 |
||
232 |
Handle<Object> SetProperty(Handle<Object> object, |
|
233 |
Handle<Object> key, |
|
234 |
Handle<Object> value, |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
235 |
PropertyAttributes attributes, |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
236 |
StrictModeFlag strict_mode) { |
237 |
Isolate* isolate = Isolate::Current(); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
238 |
CALL_HEAP_FUNCTION( |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
239 |
isolate, |
240 |
Runtime::SetObjectProperty( |
|
241 |
isolate, object, key, value, attributes, strict_mode), |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
242 |
Object); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
243 |
}
|
244 |
||
245 |
||
246 |
Handle<Object> ForceSetProperty(Handle<JSObject> object, |
|
247 |
Handle<Object> key, |
|
248 |
Handle<Object> value, |
|
249 |
PropertyAttributes attributes) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
250 |
Isolate* isolate = object->GetIsolate(); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
251 |
CALL_HEAP_FUNCTION( |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
252 |
isolate, |
253 |
Runtime::ForceSetObjectProperty( |
|
254 |
isolate, object, key, value, attributes), |
|
255 |
Object); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
256 |
}
|
257 |
||
258 |
||
259 |
Handle<Object> ForceDeleteProperty(Handle<JSObject> object, |
|
260 |
Handle<Object> key) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
261 |
Isolate* isolate = object->GetIsolate(); |
262 |
CALL_HEAP_FUNCTION(isolate, |
|
263 |
Runtime::ForceDeleteObjectProperty(isolate, object, key), |
|
264 |
Object); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
265 |
}
|
266 |
||
267 |
||
268 |
Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object, |
|
269 |
Handle<String> key, |
|
270 |
Handle<Object> value, |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
271 |
PropertyAttributes attributes, |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
272 |
StrictModeFlag strict_mode) { |
273 |
CALL_HEAP_FUNCTION(object->GetIsolate(), |
|
274 |
object->SetPropertyWithInterceptor(*key, |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
275 |
*value, |
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
276 |
attributes, |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
277 |
strict_mode), |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
278 |
Object); |
279 |
}
|
|
280 |
||
281 |
||
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
282 |
Handle<Object> GetProperty(Handle<JSReceiver> obj, |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
283 |
const char* name) { |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
284 |
Isolate* isolate = obj->GetIsolate(); |
285 |
Handle<String> str = isolate->factory()->LookupAsciiSymbol(name); |
|
286 |
CALL_HEAP_FUNCTION(isolate, obj->GetProperty(*str), Object); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
287 |
}
|
288 |
||
289 |
||
290 |
Handle<Object> GetProperty(Handle<Object> obj, |
|
291 |
Handle<Object> key) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
292 |
Isolate* isolate = Isolate::Current(); |
293 |
CALL_HEAP_FUNCTION(isolate, |
|
294 |
Runtime::GetObjectProperty(isolate, obj, key), Object); |
|
295 |
}
|
|
296 |
||
297 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
298 |
Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver, |
299 |
Handle<JSObject> holder, |
|
300 |
Handle<String> name, |
|
301 |
PropertyAttributes* attributes) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
302 |
Isolate* isolate = receiver->GetIsolate(); |
303 |
CALL_HEAP_FUNCTION(isolate, |
|
304 |
holder->GetPropertyWithInterceptor(*receiver, |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
305 |
*name, |
306 |
attributes), |
|
307 |
Object); |
|
308 |
}
|
|
309 |
||
310 |
||
1.1.1
by Jérémy Lal
Import upstream version 0.1.33 |
311 |
Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value) { |
312 |
const bool skip_hidden_prototypes = false; |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
313 |
CALL_HEAP_FUNCTION(obj->GetIsolate(), |
314 |
obj->SetPrototype(*value, skip_hidden_prototypes), Object); |
|
315 |
}
|
|
316 |
||
317 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
318 |
Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index) { |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
319 |
Isolate* isolate = Isolate::Current(); |
320 |
CALL_HEAP_FUNCTION( |
|
321 |
isolate, |
|
322 |
isolate->heap()->LookupSingleCharacterStringFromCode(index), Object); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
323 |
}
|
324 |
||
325 |
||
1.1.1
by Jérémy Lal
Import upstream version 0.1.33 |
326 |
Handle<String> SubString(Handle<String> str, |
327 |
int start, |
|
328 |
int end, |
|
329 |
PretenureFlag pretenure) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
330 |
CALL_HEAP_FUNCTION(str->GetIsolate(), |
331 |
str->SubString(start, end, pretenure), String); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
332 |
}
|
333 |
||
334 |
||
335 |
Handle<JSObject> Copy(Handle<JSObject> obj) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
336 |
Isolate* isolate = obj->GetIsolate(); |
337 |
CALL_HEAP_FUNCTION(isolate, |
|
338 |
isolate->heap()->CopyJSObject(*obj), JSObject); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
339 |
}
|
340 |
||
341 |
||
1.1.3
by Jérémy Lal
Import upstream version 0.1.97 |
342 |
Handle<Object> SetAccessor(Handle<JSObject> obj, Handle<AccessorInfo> info) { |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
343 |
CALL_HEAP_FUNCTION(obj->GetIsolate(), obj->DefineAccessor(*info), Object); |
1.1.3
by Jérémy Lal
Import upstream version 0.1.97 |
344 |
}
|
345 |
||
346 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
347 |
// Wrappers for scripts are kept alive and cached in weak global
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
348 |
// handles referred from foreign objects held by the scripts as long as
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
349 |
// they are used. When they are not used anymore, the garbage
|
350 |
// collector will call the weak callback on the global handle
|
|
351 |
// associated with the wrapper and get rid of both the wrapper and the
|
|
352 |
// handle.
|
|
353 |
static void ClearWrapperCache(Persistent<v8::Value> handle, void*) { |
|
354 |
Handle<Object> cache = Utils::OpenHandle(*handle); |
|
355 |
JSValue* wrapper = JSValue::cast(*cache); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
356 |
Foreign* foreign = Script::cast(wrapper->value())->wrapper(); |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
357 |
ASSERT(foreign->foreign_address() == |
358 |
reinterpret_cast<Address>(cache.location())); |
|
359 |
foreign->set_foreign_address(0); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
360 |
Isolate* isolate = Isolate::Current(); |
361 |
isolate->global_handles()->Destroy(cache.location()); |
|
362 |
isolate->counters()->script_wrappers()->Decrement(); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
363 |
}
|
364 |
||
365 |
||
366 |
Handle<JSValue> GetScriptWrapper(Handle<Script> script) { |
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
367 |
if (script->wrapper()->foreign_address() != NULL) { |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
368 |
// Return the script wrapper directly from the cache.
|
369 |
return Handle<JSValue>( |
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
370 |
reinterpret_cast<JSValue**>(script->wrapper()->foreign_address())); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
371 |
}
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
372 |
Isolate* isolate = Isolate::Current(); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
373 |
// Construct a new script wrapper.
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
374 |
isolate->counters()->script_wrappers()->Increment(); |
375 |
Handle<JSFunction> constructor = isolate->script_function(); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
376 |
Handle<JSValue> result = |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
377 |
Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor)); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
378 |
result->set_value(*script); |
379 |
||
380 |
// Create a new weak global handle and use it to cache the wrapper
|
|
381 |
// for future use. The cache will automatically be cleared by the
|
|
382 |
// garbage collector when it is not used anymore.
|
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
383 |
Handle<Object> handle = isolate->global_handles()->Create(*result); |
384 |
isolate->global_handles()->MakeWeak(handle.location(), NULL, |
|
385 |
&ClearWrapperCache); |
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
386 |
script->wrapper()->set_foreign_address( |
387 |
reinterpret_cast<Address>(handle.location())); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
388 |
return result; |
389 |
}
|
|
390 |
||
391 |
||
392 |
// Init line_ends array with code positions of line ends inside script
|
|
393 |
// source.
|
|
394 |
void InitScriptLineEnds(Handle<Script> script) { |
|
395 |
if (!script->line_ends()->IsUndefined()) return; |
|
396 |
||
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
397 |
Isolate* isolate = script->GetIsolate(); |
398 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
399 |
if (!script->source()->IsString()) { |
400 |
ASSERT(script->source()->IsUndefined()); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
401 |
Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0); |
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
402 |
script->set_line_ends(*empty); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
403 |
ASSERT(script->line_ends()->IsFixedArray()); |
404 |
return; |
|
405 |
}
|
|
406 |
||
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
407 |
Handle<String> src(String::cast(script->source()), isolate); |
1.1.2
by Jérémy Lal
Import upstream version 0.1.95 |
408 |
|
409 |
Handle<FixedArray> array = CalculateLineEnds(src, true); |
|
410 |
||
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
411 |
if (*array != isolate->heap()->empty_fixed_array()) { |
412 |
array->set_map(isolate->heap()->fixed_cow_array_map()); |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
413 |
}
|
414 |
||
1.1.2
by Jérémy Lal
Import upstream version 0.1.95 |
415 |
script->set_line_ends(*array); |
416 |
ASSERT(script->line_ends()->IsFixedArray()); |
|
417 |
}
|
|
418 |
||
419 |
||
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
420 |
template <typename SourceChar> |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
421 |
static void CalculateLineEnds(Isolate* isolate, |
422 |
List<int>* line_ends, |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
423 |
Vector<const SourceChar> src, |
424 |
bool with_last_line) { |
|
425 |
const int src_len = src.length(); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
426 |
StringSearch<char, SourceChar> search(isolate, CStrVector("\n")); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
427 |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
428 |
// Find and record line ends.
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
429 |
int position = 0; |
430 |
while (position != -1 && position < src_len) { |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
431 |
position = search.Search(src, position); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
432 |
if (position != -1) { |
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
433 |
line_ends->Add(position); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
434 |
position++; |
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
435 |
} else if (with_last_line) { |
1.1.2
by Jérémy Lal
Import upstream version 0.1.95 |
436 |
// Even if the last line misses a line end, it is counted.
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
437 |
line_ends->Add(src_len); |
438 |
return; |
|
439 |
}
|
|
440 |
}
|
|
441 |
}
|
|
442 |
||
443 |
||
444 |
Handle<FixedArray> CalculateLineEnds(Handle<String> src, |
|
445 |
bool with_last_line) { |
|
446 |
src = FlattenGetString(src); |
|
447 |
// Rough estimate of line count based on a roughly estimated average
|
|
448 |
// length of (unpacked) code.
|
|
449 |
int line_count_estimate = src->length() >> 4; |
|
450 |
List<int> line_ends(line_count_estimate); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
451 |
Isolate* isolate = src->GetIsolate(); |
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
452 |
{
|
453 |
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid. |
|
454 |
// Dispatch on type of strings.
|
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
455 |
String::FlatContent content = src->GetFlatContent(); |
456 |
ASSERT(content.IsFlat()); |
|
457 |
if (content.IsAscii()) { |
|
458 |
CalculateLineEnds(isolate, |
|
459 |
&line_ends, |
|
460 |
content.ToAsciiVector(), |
|
461 |
with_last_line); |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
462 |
} else { |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
463 |
CalculateLineEnds(isolate, |
464 |
&line_ends, |
|
465 |
content.ToUC16Vector(), |
|
466 |
with_last_line); |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
467 |
}
|
468 |
}
|
|
469 |
int line_count = line_ends.length(); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
470 |
Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count); |
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
471 |
for (int i = 0; i < line_count; i++) { |
472 |
array->set(i, Smi::FromInt(line_ends[i])); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
473 |
}
|
1.1.2
by Jérémy Lal
Import upstream version 0.1.95 |
474 |
return array; |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
475 |
}
|
476 |
||
477 |
||
478 |
// Convert code position into line number.
|
|
479 |
int GetScriptLineNumber(Handle<Script> script, int code_pos) { |
|
480 |
InitScriptLineEnds(script); |
|
481 |
AssertNoAllocation no_allocation; |
|
1.1.1
by Jérémy Lal
Import upstream version 0.1.33 |
482 |
FixedArray* line_ends_array = FixedArray::cast(script->line_ends()); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
483 |
const int line_ends_len = line_ends_array->length(); |
484 |
||
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
485 |
if (!line_ends_len) return -1; |
1.1.1
by Jérémy Lal
Import upstream version 0.1.33 |
486 |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
487 |
if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) { |
1.1.1
by Jérémy Lal
Import upstream version 0.1.33 |
488 |
return script->line_offset()->value(); |
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
489 |
}
|
1.1.1
by Jérémy Lal
Import upstream version 0.1.33 |
490 |
|
491 |
int left = 0; |
|
492 |
int right = line_ends_len; |
|
493 |
while (int half = (right - left) / 2) { |
|
494 |
if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) { |
|
495 |
right -= half; |
|
496 |
} else { |
|
497 |
left += half; |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
498 |
}
|
499 |
}
|
|
1.1.1
by Jérémy Lal
Import upstream version 0.1.33 |
500 |
return right + script->line_offset()->value(); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
501 |
}
|
502 |
||
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
503 |
// Convert code position into column number.
|
504 |
int GetScriptColumnNumber(Handle<Script> script, int code_pos) { |
|
505 |
int line_number = GetScriptLineNumber(script, code_pos); |
|
506 |
if (line_number == -1) return -1; |
|
507 |
||
508 |
AssertNoAllocation no_allocation; |
|
509 |
FixedArray* line_ends_array = FixedArray::cast(script->line_ends()); |
|
510 |
line_number = line_number - script->line_offset()->value(); |
|
511 |
if (line_number == 0) return code_pos + script->column_offset()->value(); |
|
512 |
int prev_line_end_pos = |
|
513 |
Smi::cast(line_ends_array->get(line_number - 1))->value(); |
|
514 |
return code_pos - (prev_line_end_pos + 1); |
|
515 |
}
|
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
516 |
|
1.1.2
by Jérémy Lal
Import upstream version 0.1.95 |
517 |
int GetScriptLineNumberSafe(Handle<Script> script, int code_pos) { |
518 |
AssertNoAllocation no_allocation; |
|
519 |
if (!script->line_ends()->IsUndefined()) { |
|
520 |
return GetScriptLineNumber(script, code_pos); |
|
521 |
}
|
|
522 |
// Slow mode: we do not have line_ends. We have to iterate through source.
|
|
523 |
if (!script->source()->IsString()) { |
|
524 |
return -1; |
|
525 |
}
|
|
526 |
String* source = String::cast(script->source()); |
|
527 |
int line = 0; |
|
528 |
int len = source->length(); |
|
529 |
for (int pos = 0; pos < len; pos++) { |
|
530 |
if (pos == code_pos) { |
|
531 |
break; |
|
532 |
}
|
|
533 |
if (source->Get(pos) == '\n') { |
|
534 |
line++; |
|
535 |
}
|
|
536 |
}
|
|
537 |
return line; |
|
538 |
}
|
|
539 |
||
540 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
541 |
void CustomArguments::IterateInstance(ObjectVisitor* v) { |
1.1.2
by Jérémy Lal
Import upstream version 0.1.95 |
542 |
v->VisitPointers(values_, values_ + ARRAY_SIZE(values_)); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
543 |
}
|
544 |
||
545 |
||
546 |
// Compute the property keys from the interceptor.
|
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
547 |
v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSReceiver> receiver, |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
548 |
Handle<JSObject> object) { |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
549 |
Isolate* isolate = receiver->GetIsolate(); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
550 |
Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
551 |
CustomArguments args(isolate, interceptor->data(), *receiver, *object); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
552 |
v8::AccessorInfo info(args.end()); |
553 |
v8::Handle<v8::Array> result; |
|
554 |
if (!interceptor->enumerator()->IsUndefined()) { |
|
555 |
v8::NamedPropertyEnumerator enum_fun = |
|
556 |
v8::ToCData<v8::NamedPropertyEnumerator>(interceptor->enumerator()); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
557 |
LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object)); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
558 |
{
|
559 |
// Leaving JavaScript.
|
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
560 |
VMState state(isolate, EXTERNAL); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
561 |
result = enum_fun(info); |
562 |
}
|
|
563 |
}
|
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
564 |
#if ENABLE_EXTRA_CHECKS
|
565 |
CHECK(result.IsEmpty() || v8::Utils::OpenHandle(*result)->IsJSObject()); |
|
566 |
#endif
|
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
567 |
return result; |
568 |
}
|
|
569 |
||
570 |
||
571 |
// Compute the element keys from the interceptor.
|
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
572 |
v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSReceiver> receiver, |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
573 |
Handle<JSObject> object) { |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
574 |
Isolate* isolate = receiver->GetIsolate(); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
575 |
Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
576 |
CustomArguments args(isolate, interceptor->data(), *receiver, *object); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
577 |
v8::AccessorInfo info(args.end()); |
578 |
v8::Handle<v8::Array> result; |
|
579 |
if (!interceptor->enumerator()->IsUndefined()) { |
|
580 |
v8::IndexedPropertyEnumerator enum_fun = |
|
581 |
v8::ToCData<v8::IndexedPropertyEnumerator>(interceptor->enumerator()); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
582 |
LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object)); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
583 |
{
|
584 |
// Leaving JavaScript.
|
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
585 |
VMState state(isolate, EXTERNAL); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
586 |
result = enum_fun(info); |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
587 |
#if ENABLE_EXTRA_CHECKS
|
588 |
CHECK(result.IsEmpty() || v8::Utils::OpenHandle(*result)->IsJSObject()); |
|
589 |
#endif
|
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
590 |
}
|
591 |
}
|
|
592 |
return result; |
|
593 |
}
|
|
594 |
||
595 |
||
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
596 |
static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { |
597 |
int len = array->length(); |
|
598 |
for (int i = 0; i < len; i++) { |
|
599 |
Object* e = array->get(i); |
|
600 |
if (!(e->IsString() || e->IsNumber())) return false; |
|
601 |
}
|
|
602 |
return true; |
|
603 |
}
|
|
604 |
||
605 |
||
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
606 |
Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSReceiver> object, |
607 |
KeyCollectionType type, |
|
608 |
bool* threw) { |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
609 |
USE(ContainsOnlyValidKeys); |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
610 |
Isolate* isolate = object->GetIsolate(); |
611 |
Handle<FixedArray> content = isolate->factory()->empty_fixed_array(); |
|
612 |
Handle<JSObject> arguments_boilerplate = Handle<JSObject>( |
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
613 |
isolate->context()->native_context()->arguments_boilerplate(), |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
614 |
isolate); |
615 |
Handle<JSFunction> arguments_function = Handle<JSFunction>( |
|
616 |
JSFunction::cast(arguments_boilerplate->map()->constructor()), |
|
617 |
isolate); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
618 |
|
619 |
// Only collect keys if access is permitted.
|
|
620 |
for (Handle<Object> p = object; |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
621 |
*p != isolate->heap()->null_value(); |
622 |
p = Handle<Object>(p->GetPrototype(), isolate)) { |
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
623 |
if (p->IsJSProxy()) { |
624 |
Handle<JSProxy> proxy(JSProxy::cast(*p), isolate); |
|
625 |
Handle<Object> args[] = { proxy }; |
|
626 |
Handle<Object> names = Execution::Call( |
|
627 |
isolate->proxy_enumerate(), object, ARRAY_SIZE(args), args, threw); |
|
628 |
if (*threw) return content; |
|
629 |
content = AddKeysFromJSArray(content, Handle<JSArray>::cast(names)); |
|
630 |
break; |
|
631 |
}
|
|
632 |
||
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
633 |
Handle<JSObject> current(JSObject::cast(*p), isolate); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
634 |
|
635 |
// Check access rights if required.
|
|
636 |
if (current->IsAccessCheckNeeded() && |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
637 |
!isolate->MayNamedAccess(*current, |
638 |
isolate->heap()->undefined_value(), |
|
639 |
v8::ACCESS_KEYS)) { |
|
640 |
isolate->ReportFailedAccessCheck(*current, v8::ACCESS_KEYS); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
641 |
break; |
642 |
}
|
|
643 |
||
644 |
// Compute the element keys.
|
|
645 |
Handle<FixedArray> element_keys = |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
646 |
isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
647 |
current->GetEnumElementKeys(*element_keys); |
648 |
content = UnionOfKeys(content, element_keys); |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
649 |
ASSERT(ContainsOnlyValidKeys(content)); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
650 |
|
651 |
// Add the element keys from the interceptor.
|
|
652 |
if (current->HasIndexedInterceptor()) { |
|
653 |
v8::Handle<v8::Array> result = |
|
654 |
GetKeysForIndexedInterceptor(object, current); |
|
655 |
if (!result.IsEmpty()) |
|
656 |
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
657 |
ASSERT(ContainsOnlyValidKeys(content)); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
658 |
}
|
659 |
||
660 |
// We can cache the computed property keys if access checks are
|
|
661 |
// not needed and no interceptors are involved.
|
|
662 |
//
|
|
663 |
// We do not use the cache if the object has elements and
|
|
664 |
// therefore it does not make sense to cache the property names
|
|
665 |
// for arguments objects. Arguments objects will always have
|
|
666 |
// elements.
|
|
1.1.6
by Jérémy Lal
Import upstream version 0.1.102 |
667 |
// Wrapped strings have elements, but don't have an elements
|
668 |
// array or dictionary. So the fast inline test for whether to
|
|
669 |
// use the cache says yes, so we should not create a cache.
|
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
670 |
bool cache_enum_keys = |
671 |
((current->map()->constructor() != *arguments_function) && |
|
1.1.6
by Jérémy Lal
Import upstream version 0.1.102 |
672 |
!current->IsJSValue() && |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
673 |
!current->IsAccessCheckNeeded() && |
674 |
!current->HasNamedInterceptor() && |
|
675 |
!current->HasIndexedInterceptor()); |
|
676 |
// Compute the property keys and cache them if possible.
|
|
677 |
content = |
|
678 |
UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys)); |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
679 |
ASSERT(ContainsOnlyValidKeys(content)); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
680 |
|
681 |
// Add the property keys from the interceptor.
|
|
682 |
if (current->HasNamedInterceptor()) { |
|
683 |
v8::Handle<v8::Array> result = |
|
684 |
GetKeysForNamedInterceptor(object, current); |
|
685 |
if (!result.IsEmpty()) |
|
686 |
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); |
|
1.1.11
by Jonas Smedegaard
Import upstream version 0.4.2 |
687 |
ASSERT(ContainsOnlyValidKeys(content)); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
688 |
}
|
689 |
||
690 |
// If we only want local properties we bail out after the first
|
|
691 |
// iteration.
|
|
692 |
if (type == LOCAL_ONLY) |
|
693 |
break; |
|
694 |
}
|
|
695 |
return content; |
|
696 |
}
|
|
697 |
||
698 |
||
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
699 |
Handle<JSArray> GetKeysFor(Handle<JSReceiver> object, bool* threw) { |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
700 |
Isolate* isolate = object->GetIsolate(); |
701 |
isolate->counters()->for_in()->Increment(); |
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
702 |
Handle<FixedArray> elements = |
703 |
GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, threw); |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
704 |
return isolate->factory()->NewJSArrayWithElements(elements); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
705 |
}
|
706 |
||
707 |
||
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
708 |
Handle<FixedArray> ReduceFixedArrayTo(Handle<FixedArray> array, int length) { |
709 |
ASSERT(array->length() >= length); |
|
710 |
if (array->length() == length) return array; |
|
711 |
||
712 |
Handle<FixedArray> new_array = |
|
713 |
array->GetIsolate()->factory()->NewFixedArray(length); |
|
714 |
for (int i = 0; i < length; ++i) new_array->set(i, array->get(i)); |
|
715 |
return new_array; |
|
716 |
}
|
|
717 |
||
718 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
719 |
Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, |
720 |
bool cache_result) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
721 |
Isolate* isolate = object->GetIsolate(); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
722 |
if (object->HasFastProperties()) { |
723 |
if (object->map()->instance_descriptors()->HasEnumCache()) { |
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
724 |
int own_property_count = object->map()->EnumLength(); |
725 |
// If we have an enum cache, but the enum length of the given map is set
|
|
726 |
// to kInvalidEnumCache, this means that the map itself has never used the
|
|
727 |
// present enum cache. The first step to using the cache is to set the
|
|
728 |
// enum length of the map by counting the number of own descriptors that
|
|
729 |
// are not DONT_ENUM.
|
|
730 |
if (own_property_count == Map::kInvalidEnumCache) { |
|
731 |
own_property_count = object->map()->NumberOfDescribedProperties( |
|
732 |
OWN_DESCRIPTORS, DONT_ENUM); |
|
733 |
||
734 |
if (cache_result) object->map()->SetEnumLength(own_property_count); |
|
735 |
}
|
|
736 |
||
737 |
DescriptorArray* desc = object->map()->instance_descriptors(); |
|
738 |
Handle<FixedArray> keys(desc->GetEnumCache(), isolate); |
|
739 |
||
740 |
// In case the number of properties required in the enum are actually
|
|
741 |
// present, we can reuse the enum cache. Otherwise, this means that the
|
|
742 |
// enum cache was generated for a previous (smaller) version of the
|
|
743 |
// Descriptor Array. In that case we regenerate the enum cache.
|
|
744 |
if (own_property_count <= keys->length()) { |
|
745 |
isolate->counters()->enum_cache_hits()->Increment(); |
|
746 |
return ReduceFixedArrayTo(keys, own_property_count); |
|
747 |
}
|
|
748 |
}
|
|
749 |
||
750 |
Handle<Map> map(object->map()); |
|
751 |
||
752 |
if (map->instance_descriptors()->IsEmpty()) { |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
753 |
isolate->counters()->enum_cache_hits()->Increment(); |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
754 |
if (cache_result) map->SetEnumLength(0); |
755 |
return isolate->factory()->empty_fixed_array(); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
756 |
}
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
757 |
|
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
758 |
isolate->counters()->enum_cache_misses()->Increment(); |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
759 |
int num_enum = map->NumberOfDescribedProperties(ALL_DESCRIPTORS, DONT_ENUM); |
760 |
||
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
761 |
Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum); |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
762 |
Handle<FixedArray> indices = isolate->factory()->NewFixedArray(num_enum); |
763 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
764 |
Handle<DescriptorArray> descs = |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
765 |
Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate); |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
766 |
|
767 |
int real_size = map->NumberOfOwnDescriptors(); |
|
768 |
int enum_size = 0; |
|
769 |
int index = 0; |
|
770 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
771 |
for (int i = 0; i < descs->number_of_descriptors(); i++) { |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
772 |
PropertyDetails details = descs->GetDetails(i); |
773 |
if (!details.IsDontEnum()) { |
|
774 |
if (i < real_size) ++enum_size; |
|
775 |
storage->set(index, descs->GetKey(i)); |
|
776 |
if (!indices.is_null()) { |
|
777 |
if (details.type() != FIELD) { |
|
778 |
indices = Handle<FixedArray>(); |
|
779 |
} else { |
|
780 |
int field_index = Descriptor::IndexFromValue(descs->GetValue(i)); |
|
781 |
if (field_index >= map->inobject_properties()) { |
|
782 |
field_index = -(field_index - map->inobject_properties() + 1); |
|
783 |
}
|
|
784 |
indices->set(index, Smi::FromInt(field_index)); |
|
785 |
}
|
|
786 |
}
|
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
787 |
index++; |
788 |
}
|
|
789 |
}
|
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
790 |
ASSERT(index == storage->length()); |
791 |
||
792 |
Handle<FixedArray> bridge_storage = |
|
793 |
isolate->factory()->NewFixedArray( |
|
794 |
DescriptorArray::kEnumCacheBridgeLength); |
|
795 |
DescriptorArray* desc = object->map()->instance_descriptors(); |
|
796 |
desc->SetEnumCache(*bridge_storage, |
|
797 |
*storage, |
|
798 |
indices.is_null() ? Object::cast(Smi::FromInt(0)) |
|
799 |
: Object::cast(*indices)); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
800 |
if (cache_result) { |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
801 |
object->map()->SetEnumLength(enum_size); |
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
802 |
}
|
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
803 |
|
804 |
return ReduceFixedArrayTo(storage, enum_size); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
805 |
} else { |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
806 |
Handle<StringDictionary> dictionary(object->property_dictionary()); |
807 |
||
808 |
int length = dictionary->NumberOfElements(); |
|
809 |
if (length == 0) { |
|
810 |
return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); |
|
811 |
}
|
|
812 |
||
813 |
// The enumeration array is generated by allocating an array big enough to
|
|
814 |
// hold all properties that have been seen, whether they are are deleted or
|
|
815 |
// not. Subsequently all visible properties are added to the array. If some
|
|
816 |
// properties were not visible, the array is trimmed so it only contains
|
|
817 |
// visible properties. This improves over adding elements and sorting by
|
|
818 |
// index by having linear complexity rather than n*log(n).
|
|
819 |
||
820 |
// By comparing the monotonous NextEnumerationIndex to the NumberOfElements,
|
|
821 |
// we can predict the number of holes in the final array. If there will be
|
|
822 |
// more than 50% holes, regenerate the enumeration indices to reduce the
|
|
823 |
// number of holes to a minimum. This avoids allocating a large array if
|
|
824 |
// many properties were added but subsequently deleted.
|
|
825 |
int next_enumeration = dictionary->NextEnumerationIndex(); |
|
826 |
if (!object->IsGlobalObject() && next_enumeration > (length * 3) / 2) { |
|
827 |
StringDictionary::DoGenerateNewEnumerationIndices(dictionary); |
|
828 |
next_enumeration = dictionary->NextEnumerationIndex(); |
|
829 |
}
|
|
830 |
||
831 |
Handle<FixedArray> storage = |
|
832 |
isolate->factory()->NewFixedArray(next_enumeration); |
|
833 |
||
834 |
storage = Handle<FixedArray>(dictionary->CopyEnumKeysTo(*storage)); |
|
835 |
ASSERT(storage->length() == object->NumberOfLocalProperties(DONT_ENUM)); |
|
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
836 |
return storage; |
837 |
}
|
|
838 |
}
|
|
839 |
||
840 |
||
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
841 |
Handle<ObjectHashSet> ObjectHashSetAdd(Handle<ObjectHashSet> table, |
842 |
Handle<Object> key) { |
|
843 |
CALL_HEAP_FUNCTION(table->GetIsolate(), |
|
844 |
table->Add(*key), |
|
845 |
ObjectHashSet); |
|
846 |
}
|
|
847 |
||
848 |
||
849 |
Handle<ObjectHashSet> ObjectHashSetRemove(Handle<ObjectHashSet> table, |
|
850 |
Handle<Object> key) { |
|
851 |
CALL_HEAP_FUNCTION(table->GetIsolate(), |
|
852 |
table->Remove(*key), |
|
853 |
ObjectHashSet); |
|
854 |
}
|
|
855 |
||
856 |
||
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
857 |
Handle<ObjectHashTable> PutIntoObjectHashTable(Handle<ObjectHashTable> table, |
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
858 |
Handle<Object> key, |
1.1.12
by Jérémy Lal
Import upstream version 0.6.8~dfsg1 |
859 |
Handle<Object> value) { |
860 |
CALL_HEAP_FUNCTION(table->GetIsolate(), |
|
861 |
table->Put(*key, *value), |
|
862 |
ObjectHashTable); |
|
863 |
}
|
|
864 |
||
865 |
||
1.1.13
by Jonas Smedegaard
Import upstream version 0.10.0~dfsg1 |
866 |
// This method determines the type of string involved and then gets the UTF8
|
867 |
// length of the string. It doesn't flatten the string and has log(n) recursion
|
|
868 |
// for a string of length n. If the failure flag gets set, then we have to
|
|
869 |
// flatten the string and retry. Failures are caused by surrogate pairs in deep
|
|
870 |
// cons strings.
|
|
871 |
||
872 |
// Single surrogate characters that are encountered in the UTF-16 character
|
|
873 |
// sequence of the input string get counted as 3 UTF-8 bytes, because that
|
|
874 |
// is the way that WriteUtf8 will encode them. Surrogate pairs are counted and
|
|
875 |
// encoded as one 4-byte UTF-8 sequence.
|
|
876 |
||
877 |
// This function conceptually uses recursion on the two halves of cons strings.
|
|
878 |
// However, in order to avoid the recursion going too deep it recurses on the
|
|
879 |
// second string of the cons, but iterates on the first substring (by manually
|
|
880 |
// eliminating it as a tail recursion). This means it counts the UTF-8 length
|
|
881 |
// from the end to the start, which makes no difference to the total.
|
|
882 |
||
883 |
// Surrogate pairs are recognized even if they are split across two sides of a
|
|
884 |
// cons, which complicates the implementation somewhat. Therefore, too deep
|
|
885 |
// recursion cannot always be avoided. This case is detected, and the failure
|
|
886 |
// flag is set, a signal to the caller that the string should be flattened and
|
|
887 |
// the operation retried.
|
|
888 |
int Utf8LengthHelper(String* input, |
|
889 |
int from, |
|
890 |
int to, |
|
891 |
bool followed_by_surrogate, |
|
892 |
int max_recursion, |
|
893 |
bool* failure, |
|
894 |
bool* starts_with_surrogate) { |
|
895 |
if (from == to) return 0; |
|
896 |
int total = 0; |
|
897 |
bool dummy; |
|
898 |
while (true) { |
|
899 |
if (input->IsAsciiRepresentation()) { |
|
900 |
*starts_with_surrogate = false; |
|
901 |
return total + to - from; |
|
902 |
}
|
|
903 |
switch (StringShape(input).representation_tag()) { |
|
904 |
case kConsStringTag: { |
|
905 |
ConsString* str = ConsString::cast(input); |
|
906 |
String* first = str->first(); |
|
907 |
String* second = str->second(); |
|
908 |
int first_length = first->length(); |
|
909 |
if (first_length - from > to - first_length) { |
|
910 |
if (first_length < to) { |
|
911 |
// Right hand side is shorter. No need to check the recursion depth
|
|
912 |
// since this can only happen log(n) times.
|
|
913 |
bool right_starts_with_surrogate = false; |
|
914 |
total += Utf8LengthHelper(second, |
|
915 |
0, |
|
916 |
to - first_length, |
|
917 |
followed_by_surrogate, |
|
918 |
max_recursion - 1, |
|
919 |
failure, |
|
920 |
&right_starts_with_surrogate); |
|
921 |
if (*failure) return 0; |
|
922 |
followed_by_surrogate = right_starts_with_surrogate; |
|
923 |
input = first; |
|
924 |
to = first_length; |
|
925 |
} else { |
|
926 |
// We only need the left hand side.
|
|
927 |
input = first; |
|
928 |
}
|
|
929 |
} else { |
|
930 |
if (first_length > from) { |
|
931 |
// Left hand side is shorter.
|
|
932 |
if (first->IsAsciiRepresentation()) { |
|
933 |
total += first_length - from; |
|
934 |
*starts_with_surrogate = false; |
|
935 |
starts_with_surrogate = &dummy; |
|
936 |
input = second; |
|
937 |
from = 0; |
|
938 |
to -= first_length; |
|
939 |
} else if (second->IsAsciiRepresentation()) { |
|
940 |
followed_by_surrogate = false; |
|
941 |
total += to - first_length; |
|
942 |
input = first; |
|
943 |
to = first_length; |
|
944 |
} else if (max_recursion > 0) { |
|
945 |
bool right_starts_with_surrogate = false; |
|
946 |
// Recursing on the long one. This may fail.
|
|
947 |
total += Utf8LengthHelper(second, |
|
948 |
0, |
|
949 |
to - first_length, |
|
950 |
followed_by_surrogate, |
|
951 |
max_recursion - 1, |
|
952 |
failure, |
|
953 |
&right_starts_with_surrogate); |
|
954 |
if (*failure) return 0; |
|
955 |
input = first; |
|
956 |
to = first_length; |
|
957 |
followed_by_surrogate = right_starts_with_surrogate; |
|
958 |
} else { |
|
959 |
*failure = true; |
|
960 |
return 0; |
|
961 |
}
|
|
962 |
} else { |
|
963 |
// We only need the right hand side.
|
|
964 |
input = second; |
|
965 |
from = 0; |
|
966 |
to -= first_length; |
|
967 |
}
|
|
968 |
}
|
|
969 |
continue; |
|
970 |
}
|
|
971 |
case kExternalStringTag: |
|
972 |
case kSeqStringTag: { |
|
973 |
Vector<const uc16> vector = input->GetFlatContent().ToUC16Vector(); |
|
974 |
const uc16* p = vector.start(); |
|
975 |
int previous = unibrow::Utf16::kNoPreviousCharacter; |
|
976 |
for (int i = from; i < to; i++) { |
|
977 |
uc16 c = p[i]; |
|
978 |
total += unibrow::Utf8::Length(c, previous); |
|
979 |
previous = c; |
|
980 |
}
|
|
981 |
if (to - from > 0) { |
|
982 |
if (unibrow::Utf16::IsLeadSurrogate(previous) && |
|
983 |
followed_by_surrogate) { |
|
984 |
total -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; |
|
985 |
}
|
|
986 |
if (unibrow::Utf16::IsTrailSurrogate(p[from])) { |
|
987 |
*starts_with_surrogate = true; |
|
988 |
}
|
|
989 |
}
|
|
990 |
return total; |
|
991 |
}
|
|
992 |
case kSlicedStringTag: { |
|
993 |
SlicedString* str = SlicedString::cast(input); |
|
994 |
int offset = str->offset(); |
|
995 |
input = str->parent(); |
|
996 |
from += offset; |
|
997 |
to += offset; |
|
998 |
continue; |
|
999 |
}
|
|
1000 |
default: |
|
1001 |
break; |
|
1002 |
}
|
|
1003 |
UNREACHABLE(); |
|
1004 |
return 0; |
|
1005 |
}
|
|
1006 |
return 0; |
|
1007 |
}
|
|
1008 |
||
1009 |
||
1010 |
int Utf8Length(Handle<String> str) { |
|
1011 |
bool dummy; |
|
1012 |
bool failure; |
|
1013 |
int len; |
|
1014 |
const int kRecursionBudget = 100; |
|
1015 |
do { |
|
1016 |
failure = false; |
|
1017 |
len = Utf8LengthHelper( |
|
1018 |
*str, 0, str->length(), false, kRecursionBudget, &failure, &dummy); |
|
1019 |
if (failure) FlattenString(str); |
|
1020 |
} while (failure); |
|
1021 |
return len; |
|
1022 |
}
|
|
1023 |
||
1024 |
||
1025 |
DeferredHandleScope::DeferredHandleScope(Isolate* isolate) |
|
1026 |
: impl_(isolate->handle_scope_implementer()) { |
|
1027 |
ASSERT(impl_->isolate() == Isolate::Current()); |
|
1028 |
impl_->BeginDeferredScope(); |
|
1029 |
v8::ImplementationUtilities::HandleScopeData* data = |
|
1030 |
impl_->isolate()->handle_scope_data(); |
|
1031 |
Object** new_next = impl_->GetSpareOrNewBlock(); |
|
1032 |
Object** new_limit = &new_next[kHandleBlockSize]; |
|
1033 |
ASSERT(data->limit == &impl_->blocks()->last()[kHandleBlockSize]); |
|
1034 |
impl_->blocks()->Add(new_next); |
|
1035 |
||
1036 |
#ifdef DEBUG
|
|
1037 |
prev_level_ = data->level; |
|
1038 |
#endif
|
|
1039 |
data->level++; |
|
1040 |
prev_limit_ = data->limit; |
|
1041 |
prev_next_ = data->next; |
|
1042 |
data->next = new_next; |
|
1043 |
data->limit = new_limit; |
|
1044 |
}
|
|
1045 |
||
1046 |
||
1047 |
DeferredHandleScope::~DeferredHandleScope() { |
|
1048 |
impl_->isolate()->handle_scope_data()->level--; |
|
1049 |
ASSERT(handles_detached_); |
|
1050 |
ASSERT(impl_->isolate()->handle_scope_data()->level == prev_level_); |
|
1051 |
}
|
|
1052 |
||
1053 |
||
1054 |
DeferredHandles* DeferredHandleScope::Detach() { |
|
1055 |
DeferredHandles* deferred = impl_->Detach(prev_limit_); |
|
1056 |
v8::ImplementationUtilities::HandleScopeData* data = |
|
1057 |
impl_->isolate()->handle_scope_data(); |
|
1058 |
data->next = prev_next_; |
|
1059 |
data->limit = prev_limit_; |
|
1060 |
#ifdef DEBUG
|
|
1061 |
handles_detached_ = true; |
|
1062 |
#endif
|
|
1063 |
return deferred; |
|
1064 |
}
|
|
1065 |
||
1
by Jérémy Lal
Import upstream version 0.1.27+dfsg |
1066 |
|
1067 |
} } // namespace v8::internal |