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

Side by Side Diff: src/execution.cc

Issue 242014: Adds an API for setting the stack limit per-thread. (Closed)
Patch Set: Leaves the limits of pending interrupts alone instead of reestablishing them." 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
« 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 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 215
216 // Static state for stack guards. 216 // Static state for stack guards.
217 StackGuard::ThreadLocal StackGuard::thread_local_; 217 StackGuard::ThreadLocal StackGuard::thread_local_;
218 218
219 219
220 StackGuard::StackGuard() { 220 StackGuard::StackGuard() {
221 // NOTE: Overall the StackGuard code assumes that the stack grows towards 221 // NOTE: Overall the StackGuard code assumes that the stack grows towards
222 // lower addresses. 222 // lower addresses.
223 ExecutionAccess access; 223 ExecutionAccess access;
224 if (thread_local_.nesting_++ == 0) { 224 if (thread_local_.nesting_++ == 0) {
225 // Initial StackGuard is being set. We will set the stack limits based on 225 // Initial StackGuard is being set.
226 // the current stack pointer allowing the stack to grow kLimitSize from
227 // here.
228 226
229 // Ensure that either the stack limits are unset (kIllegalLimit) or that 227 // Ensure that either the stack limits are unset (kIllegalLimit) or that
230 // they indicate a pending interruption. The interrupt limit will be 228 // they indicate a pending interruption. The interrupt limit will be
231 // temporarily reset through the code below and reestablished if the 229 // temporarily reset through the code below and reestablished if the
232 // interrupt flags indicate that an interrupt is pending. 230 // interrupt flags indicate that an interrupt is pending.
233 ASSERT(thread_local_.jslimit_ == kIllegalLimit || 231 ASSERT(thread_local_.jslimit_ == kIllegalLimit ||
234 (thread_local_.jslimit_ == kInterruptLimit && 232 (thread_local_.jslimit_ == kInterruptLimit &&
235 thread_local_.interrupt_flags_ != 0)); 233 thread_local_.interrupt_flags_ != 0));
236 ASSERT(thread_local_.climit_ == kIllegalLimit || 234 ASSERT(thread_local_.climit_ == kIllegalLimit ||
237 (thread_local_.climit_ == kInterruptLimit && 235 (thread_local_.climit_ == kInterruptLimit &&
238 thread_local_.interrupt_flags_ != 0)); 236 thread_local_.interrupt_flags_ != 0));
239 237
240 uintptr_t limit = GENERATED_CODE_STACK_LIMIT(kLimitSize); 238 if (thread_local_.initial_jslimit_ == kIllegalLimit ||
241 thread_local_.initial_jslimit_ = thread_local_.jslimit_ = limit; 239 thread_local_.initial_climit_ == kIllegalLimit) {
242 Heap::SetStackLimit(limit); 240 ASSERT(thread_local_.initial_jslimit_ == kIllegalLimit &&
243 // NOTE: The check for overflow is not safe as there is no guarantee that 241 thread_local_.initial_climit_ == kIllegalLimit);
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 242
249 if (thread_local_.interrupt_flags_ != 0) { 243 // We will set the stack limits based on the current stack
250 set_limits(kInterruptLimit, access); 244 // pointer allowing the stack to grow kLimitSize from here.
245
246 // Compute default limit, checking for underflow.
247 uintptr_t limit =
248 reinterpret_cast<uintptr_t>(this) >= kLimitSize ?
249 reinterpret_cast<uintptr_t>(this) - kLimitSize : 0;
250
251 thread_local_.initial_jslimit_ = GENERATED_CODE_STACK_LIMIT(limit);
252 thread_local_.initial_climit_ = limit;
253 }
254
255 if (thread_local_.interrupt_flags_ == 0) {
256 set_limits(thread_local_.initial_jslimit_, thread_local_.initial_climit_,
257 access);
251 } 258 }
252 } 259 }
253 // Ensure that proper limits have been set. 260 // Ensure that proper limits have been set.
254 ASSERT(thread_local_.jslimit_ != kIllegalLimit && 261 ASSERT(thread_local_.jslimit_ != kIllegalLimit &&
255 thread_local_.climit_ != kIllegalLimit); 262 thread_local_.climit_ != kIllegalLimit);
256 ASSERT(thread_local_.initial_jslimit_ != kIllegalLimit && 263 ASSERT(thread_local_.initial_jslimit_ != kIllegalLimit &&
257 thread_local_.initial_climit_ != kIllegalLimit); 264 thread_local_.initial_climit_ != kIllegalLimit);
258 } 265 }
259 266
260 267
261 StackGuard::~StackGuard() { 268 StackGuard::~StackGuard() {
262 ExecutionAccess access; 269 ExecutionAccess access;
263 if (--thread_local_.nesting_ == 0) { 270 if (--thread_local_.nesting_ == 0 &&
264 set_limits(kIllegalLimit, access); 271 thread_local_.interrupt_flags_ == 0) {
272 set_illegal_limit(access);
265 } 273 }
266 } 274 }
267 275
268 276
269 bool StackGuard::IsStackOverflow() { 277 bool StackGuard::IsStackOverflow() {
270 ExecutionAccess access; 278 ExecutionAccess access;
271 return (thread_local_.jslimit_ != kInterruptLimit && 279 return (thread_local_.jslimit_ != kInterruptLimit &&
272 thread_local_.climit_ != kInterruptLimit); 280 thread_local_.climit_ != kInterruptLimit);
273 } 281 }
274 282
275 283
276 void StackGuard::EnableInterrupts() { 284 void StackGuard::EnableInterrupts() {
277 ExecutionAccess access; 285 ExecutionAccess access;
278 if (IsSet(access)) { 286 if (IsSet(access)) {
279 set_limits(kInterruptLimit, access); 287 set_interrupt_limit(access);
280 } 288 }
281 } 289 }
282 290
283 291
284 void StackGuard::SetStackLimit(uintptr_t limit) { 292 void StackGuard::SetStackLimit(uintptr_t limit) {
285 ExecutionAccess access; 293 ExecutionAccess access;
286 // If the current limits are special (eg due to a pending interrupt) then 294 thread_local_.initial_jslimit_ = GENERATED_CODE_STACK_LIMIT(limit);
287 // leave them alone. 295 thread_local_.initial_climit_ = limit;
288 if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) { 296
289 thread_local_.jslimit_ = limit; 297 // If a StackGuard is active (nesting_ > 0) and not interrupted set
290 Heap::SetStackLimit(limit); 298 // the limit directly. Otherwise the limit will be established by
299 // the first StackGuard.
300 if (thread_local_.nesting_ > 0 &&
301 thread_local_.interrupt_flags_ == 0) {
302 set_limits(thread_local_.initial_jslimit_, thread_local_.initial_climit_,
303 access);
291 } 304 }
292 if (thread_local_.climit_ == thread_local_.initial_climit_) {
293 thread_local_.climit_ = limit;
294 }
295 thread_local_.initial_climit_ = limit;
296 thread_local_.initial_jslimit_ = limit;
297 } 305 }
298 306
299 307
300 void StackGuard::DisableInterrupts() { 308 void StackGuard::DisableInterrupts() {
301 ExecutionAccess access; 309 ExecutionAccess access;
302 reset_limits(access); 310 reset_limits(access);
303 } 311 }
304 312
305 313
306 bool StackGuard::IsSet(const ExecutionAccess& lock) { 314 bool StackGuard::IsSet(const ExecutionAccess& lock) {
307 return thread_local_.interrupt_flags_ != 0; 315 return thread_local_.interrupt_flags_ != 0;
308 } 316 }
309 317
310 318
311 bool StackGuard::IsInterrupted() { 319 bool StackGuard::IsInterrupted() {
312 ExecutionAccess access; 320 ExecutionAccess access;
313 return thread_local_.interrupt_flags_ & INTERRUPT; 321 return thread_local_.interrupt_flags_ & INTERRUPT;
314 } 322 }
315 323
316 324
317 void StackGuard::Interrupt() { 325 void StackGuard::Interrupt() {
318 ExecutionAccess access; 326 ExecutionAccess access;
319 thread_local_.interrupt_flags_ |= INTERRUPT; 327 thread_local_.interrupt_flags_ |= INTERRUPT;
320 set_limits(kInterruptLimit, access); 328 set_interrupt_limit(access);
321 } 329 }
322 330
323 331
324 bool StackGuard::IsPreempted() { 332 bool StackGuard::IsPreempted() {
325 ExecutionAccess access; 333 ExecutionAccess access;
326 return thread_local_.interrupt_flags_ & PREEMPT; 334 return thread_local_.interrupt_flags_ & PREEMPT;
327 } 335 }
328 336
329 337
330 void StackGuard::Preempt() { 338 void StackGuard::Preempt() {
331 ExecutionAccess access; 339 ExecutionAccess access;
332 thread_local_.interrupt_flags_ |= PREEMPT; 340 thread_local_.interrupt_flags_ |= PREEMPT;
333 set_limits(kInterruptLimit, access); 341 set_interrupt_limit(access);
334 } 342 }
335 343
336 344
337 bool StackGuard::IsTerminateExecution() { 345 bool StackGuard::IsTerminateExecution() {
338 ExecutionAccess access; 346 ExecutionAccess access;
339 return thread_local_.interrupt_flags_ & TERMINATE; 347 return thread_local_.interrupt_flags_ & TERMINATE;
340 } 348 }
341 349
342 350
343 void StackGuard::TerminateExecution() { 351 void StackGuard::TerminateExecution() {
344 ExecutionAccess access; 352 ExecutionAccess access;
345 thread_local_.interrupt_flags_ |= TERMINATE; 353 thread_local_.interrupt_flags_ |= TERMINATE;
346 set_limits(kInterruptLimit, access); 354 set_interrupt_limit(access);
347 } 355 }
348 356
349 357
350 #ifdef ENABLE_DEBUGGER_SUPPORT 358 #ifdef ENABLE_DEBUGGER_SUPPORT
351 bool StackGuard::IsDebugBreak() { 359 bool StackGuard::IsDebugBreak() {
352 ExecutionAccess access; 360 ExecutionAccess access;
353 return thread_local_.interrupt_flags_ & DEBUGBREAK; 361 return thread_local_.interrupt_flags_ & DEBUGBREAK;
354 } 362 }
355 363
356 364
357 void StackGuard::DebugBreak() { 365 void StackGuard::DebugBreak() {
358 ExecutionAccess access; 366 ExecutionAccess access;
359 thread_local_.interrupt_flags_ |= DEBUGBREAK; 367 thread_local_.interrupt_flags_ |= DEBUGBREAK;
360 set_limits(kInterruptLimit, access); 368 set_interrupt_limit(access);
361 } 369 }
362 370
363 371
364 bool StackGuard::IsDebugCommand() { 372 bool StackGuard::IsDebugCommand() {
365 ExecutionAccess access; 373 ExecutionAccess access;
366 return thread_local_.interrupt_flags_ & DEBUGCOMMAND; 374 return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
367 } 375 }
368 376
369 377
370 void StackGuard::DebugCommand() { 378 void StackGuard::DebugCommand() {
371 if (FLAG_debugger_auto_break) { 379 if (FLAG_debugger_auto_break) {
372 ExecutionAccess access; 380 ExecutionAccess access;
373 thread_local_.interrupt_flags_ |= DEBUGCOMMAND; 381 thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
374 set_limits(kInterruptLimit, access); 382 set_interrupt_limit(access);
375 } 383 }
376 } 384 }
377 #endif 385 #endif
378 386
379 void StackGuard::Continue(InterruptFlag after_what) { 387 void StackGuard::Continue(InterruptFlag after_what) {
380 ExecutionAccess access; 388 ExecutionAccess access;
381 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); 389 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
382 if (thread_local_.interrupt_flags_ == 0) { 390 if (thread_local_.interrupt_flags_ == 0) {
383 reset_limits(access); 391 reset_limits(access);
384 } 392 }
(...skipping 15 matching lines...) Expand all
400 408
401 409
402 char* StackGuard::RestoreStackGuard(char* from) { 410 char* StackGuard::RestoreStackGuard(char* from) {
403 ExecutionAccess access; 411 ExecutionAccess access;
404 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); 412 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
405 Heap::SetStackLimit(thread_local_.jslimit_); 413 Heap::SetStackLimit(thread_local_.jslimit_);
406 return from + sizeof(ThreadLocal); 414 return from + sizeof(ThreadLocal);
407 } 415 }
408 416
409 417
418 void StackGuard::InitThread(const ExecutionAccess& lock) {
419 // new threads should configure their own stack limits
420 ThreadLocal blank;
421 thread_local_ = blank;
422 }
423
424
410 // --- C a l l s t o n a t i v e s --- 425 // --- C a l l s t o n a t i v e s ---
411 426
412 #define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \ 427 #define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \
413 do { \ 428 do { \
414 Object** args[argc] = argv; \ 429 Object** args[argc] = argv; \
415 ASSERT(has_pending_exception != NULL); \ 430 ASSERT(has_pending_exception != NULL); \
416 return Call(Top::name##_fun(), Top::builtins(), argc, args, \ 431 return Call(Top::name##_fun(), Top::builtins(), argc, args, \
417 has_pending_exception); \ 432 has_pending_exception); \
418 } while (false) 433 } while (false)
419 434
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 // All allocation spaces other than NEW_SPACE have the same effect. 700 // All allocation spaces other than NEW_SPACE have the same effect.
686 Heap::CollectAllGarbage(false); 701 Heap::CollectAllGarbage(false);
687 return v8::Undefined(); 702 return v8::Undefined();
688 } 703 }
689 704
690 705
691 static GCExtension kGCExtension; 706 static GCExtension kGCExtension;
692 v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension); 707 v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension);
693 708
694 } } // namespace v8::internal 709 } } // 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