Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(573)

Side by Side Diff: src/execution.cc

Issue 242074: Fix the stack limits setting API so it is usable. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/execution.h ('k') | src/ia32/simulator-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 Handle<Object> receiver, 54 Handle<Object> receiver,
55 int argc, 55 int argc,
56 Object*** args, 56 Object*** args,
57 bool* has_pending_exception) { 57 bool* has_pending_exception) {
58 // Make sure we have a real function, not a boilerplate function. 58 // Make sure we have a real function, not a boilerplate function.
59 ASSERT(!func->IsBoilerplate()); 59 ASSERT(!func->IsBoilerplate());
60 60
61 // Entering JavaScript. 61 // Entering JavaScript.
62 VMState state(JS); 62 VMState state(JS);
63 63
64 // Guard the stack against too much recursion.
65 StackGuard guard;
66
67 // Placeholder for return value. 64 // Placeholder for return value.
68 Object* value = reinterpret_cast<Object*>(kZapValue); 65 Object* value = reinterpret_cast<Object*>(kZapValue);
69 66
70 typedef Object* (*JSEntryFunction)( 67 typedef Object* (*JSEntryFunction)(
71 byte* entry, 68 byte* entry,
72 Object* function, 69 Object* function,
73 Object* receiver, 70 Object* receiver,
74 int argc, 71 int argc,
75 Object*** args); 72 Object*** args);
76 73
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 } 207 }
211 208
212 return Factory::undefined_value(); 209 return Factory::undefined_value();
213 } 210 }
214 211
215 212
216 // Static state for stack guards. 213 // Static state for stack guards.
217 StackGuard::ThreadLocal StackGuard::thread_local_; 214 StackGuard::ThreadLocal StackGuard::thread_local_;
218 215
219 216
220 StackGuard::StackGuard() {
221 // NOTE: Overall the StackGuard code assumes that the stack grows towards
222 // lower addresses.
223 ExecutionAccess access;
224 if (thread_local_.nesting_++ == 0) {
225 // Initial StackGuard is being set. We will set the stack limits based on
226 // the current stack pointer allowing the stack to grow kLimitSize from
227 // here.
228
229 // Ensure that either the stack limits are unset (kIllegalLimit) or that
230 // they indicate a pending interruption. The interrupt limit will be
231 // temporarily reset through the code below and reestablished if the
232 // interrupt flags indicate that an interrupt is pending.
233 ASSERT(thread_local_.jslimit_ == kIllegalLimit ||
234 (thread_local_.jslimit_ == kInterruptLimit &&
235 thread_local_.interrupt_flags_ != 0));
236 ASSERT(thread_local_.climit_ == kIllegalLimit ||
237 (thread_local_.climit_ == kInterruptLimit &&
238 thread_local_.interrupt_flags_ != 0));
239
240 uintptr_t limit = GENERATED_CODE_STACK_LIMIT(kLimitSize);
241 thread_local_.initial_jslimit_ = thread_local_.jslimit_ = limit;
242 Heap::SetStackLimit(limit);
243 // NOTE: The check for overflow is not safe as there is no guarantee that
244 // the running thread has its stack in all memory up to address 0x00000000.
245 thread_local_.initial_climit_ = thread_local_.climit_ =
246 reinterpret_cast<uintptr_t>(this) >= kLimitSize ?
247 reinterpret_cast<uintptr_t>(this) - kLimitSize : 0;
248
249 if (thread_local_.interrupt_flags_ != 0) {
250 set_limits(kInterruptLimit, access);
251 }
252 }
253 // Ensure that proper limits have been set.
254 ASSERT(thread_local_.jslimit_ != kIllegalLimit &&
255 thread_local_.climit_ != kIllegalLimit);
256 ASSERT(thread_local_.initial_jslimit_ != kIllegalLimit &&
257 thread_local_.initial_climit_ != kIllegalLimit);
258 }
259
260
261 StackGuard::~StackGuard() {
262 ExecutionAccess access;
263 if (--thread_local_.nesting_ == 0) {
264 set_limits(kIllegalLimit, access);
265 }
266 }
267
268
269 bool StackGuard::IsStackOverflow() { 217 bool StackGuard::IsStackOverflow() {
270 ExecutionAccess access; 218 ExecutionAccess access;
271 return (thread_local_.jslimit_ != kInterruptLimit && 219 return (thread_local_.jslimit_ != kInterruptLimit &&
272 thread_local_.climit_ != kInterruptLimit); 220 thread_local_.climit_ != kInterruptLimit);
273 } 221 }
274 222
275 223
276 void StackGuard::EnableInterrupts() { 224 void StackGuard::EnableInterrupts() {
277 ExecutionAccess access; 225 ExecutionAccess access;
278 if (IsSet(access)) { 226 if (IsSet(access)) {
279 set_limits(kInterruptLimit, access); 227 set_limits(kInterruptLimit, access);
280 } 228 }
281 } 229 }
282 230
283 231
284 void StackGuard::SetStackLimit(uintptr_t limit) { 232 void StackGuard::SetStackLimit(uintptr_t limit) {
285 ExecutionAccess access; 233 ExecutionAccess access;
286 // If the current limits are special (eg due to a pending interrupt) then 234 // If the current limits are special (eg due to a pending interrupt) then
287 // leave them alone. 235 // leave them alone.
236 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(limit);
288 if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) { 237 if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) {
289 thread_local_.jslimit_ = limit; 238 thread_local_.jslimit_ = jslimit;
290 Heap::SetStackLimit(limit); 239 Heap::SetStackLimit(jslimit);
291 } 240 }
292 if (thread_local_.climit_ == thread_local_.initial_climit_) { 241 if (thread_local_.climit_ == thread_local_.initial_climit_) {
293 thread_local_.climit_ = limit; 242 thread_local_.climit_ = limit;
294 } 243 }
295 thread_local_.initial_climit_ = limit; 244 thread_local_.initial_climit_ = limit;
296 thread_local_.initial_jslimit_ = limit; 245 thread_local_.initial_jslimit_ = jslimit;
297 } 246 }
298 247
299 248
300 void StackGuard::DisableInterrupts() { 249 void StackGuard::DisableInterrupts() {
301 ExecutionAccess access; 250 ExecutionAccess access;
302 reset_limits(access); 251 reset_limits(access);
303 } 252 }
304 253
305 254
306 bool StackGuard::IsSet(const ExecutionAccess& lock) { 255 bool StackGuard::IsSet(const ExecutionAccess& lock) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 349
401 350
402 char* StackGuard::RestoreStackGuard(char* from) { 351 char* StackGuard::RestoreStackGuard(char* from) {
403 ExecutionAccess access; 352 ExecutionAccess access;
404 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); 353 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
405 Heap::SetStackLimit(thread_local_.jslimit_); 354 Heap::SetStackLimit(thread_local_.jslimit_);
406 return from + sizeof(ThreadLocal); 355 return from + sizeof(ThreadLocal);
407 } 356 }
408 357
409 358
359 static internal::Thread::LocalStorageKey stack_limit_key =
360 internal::Thread::CreateThreadLocalKey();
361
362
410 void StackGuard::FreeThreadResources() { 363 void StackGuard::FreeThreadResources() {
364 Thread::SetThreadLocal(
365 stack_limit_key,
366 reinterpret_cast<void*>(thread_local_.initial_climit_));
367 }
368
369
370 void StackGuard::ThreadLocal::Clear() {
371 initial_jslimit_ = kIllegalLimit;
372 jslimit_ = kIllegalLimit;
373 initial_climit_ = kIllegalLimit;
374 climit_ = kIllegalLimit;
375 nesting_ = 0;
376 postpone_interrupts_nesting_ = 0;
377 interrupt_flags_ = 0;
378 Heap::SetStackLimit(kIllegalLimit);
379 }
380
381
382 void StackGuard::ThreadLocal::Initialize() {
383 if (initial_climit_ == kIllegalLimit) {
384 // Takes the address of the limit variable in order to find out where
385 // the top of stack is right now.
386 intptr_t limit = reinterpret_cast<intptr_t>(&limit) - kLimitSize;
387 initial_jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
388 jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
389 initial_climit_ = limit;
390 climit_ = limit;
391 Heap::SetStackLimit(SimulatorStack::JsLimitFromCLimit(limit));
392 }
393 nesting_ = 0;
394 postpone_interrupts_nesting_ = 0;
395 interrupt_flags_ = 0;
396 }
397
398
399 void StackGuard::ClearThread(const ExecutionAccess& lock) {
400 thread_local_.Clear();
401 }
402
403
404 void StackGuard::InitThread(const ExecutionAccess& lock) {
405 thread_local_.Initialize();
406 void* stored_limit = Thread::GetThreadLocal(stack_limit_key);
407 // You should hold the ExecutionAccess lock when you call this.
408 if (stored_limit != NULL) {
409 StackGuard::SetStackLimit(reinterpret_cast<intptr_t>(stored_limit));
410 }
411 } 411 }
412 412
413 413
414 // --- C a l l s t o n a t i v e s --- 414 // --- C a l l s t o n a t i v e s ---
415 415
416 #define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \ 416 #define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \
417 do { \ 417 do { \
418 Object** args[argc] = argv; \ 418 Object** args[argc] = argv; \
419 ASSERT(has_pending_exception != NULL); \ 419 ASSERT(has_pending_exception != NULL); \
420 return Call(Top::name##_fun(), Top::builtins(), argc, args, \ 420 return Call(Top::name##_fun(), Top::builtins(), argc, args, \
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 // All allocation spaces other than NEW_SPACE have the same effect. 689 // All allocation spaces other than NEW_SPACE have the same effect.
690 Heap::CollectAllGarbage(false); 690 Heap::CollectAllGarbage(false);
691 return v8::Undefined(); 691 return v8::Undefined();
692 } 692 }
693 693
694 694
695 static GCExtension kGCExtension; 695 static GCExtension kGCExtension;
696 v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension); 696 v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension);
697 697
698 } } // namespace v8::internal 698 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/execution.h ('k') | src/ia32/simulator-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698