v8/src/handles.cc
yangguo 8bcef0d73d Revert of Canonicalize handles for optimized compilation. (patchset #1 id:1 of https://codereview.chromium.org/1423833003/ )
Reason for revert:
GC stress failure on ia32 optdebug:

/tmp/runfswAKT/out/Debug/d8 --test --random-seed=-1536184370 --turbo --always-opt --nohard-abort --nodead-code-elimination --nofold-constants --enable-slow-asserts --debug-code --verify-heap --stack-size=46 /tmp/runfswAKT/test/mjsunit/mjsunit.js /tmp/runfswAKT/test/mjsunit/regress/regress-1132.js --gc-interval=500 --stress-compaction --concurrent-recompilation-queue-length=64 --concurrent-recompilation-delay=500 --concurrent-recompilation

Run #1
Exit code: -6
Result: FAIL
Expected outcomes: PASS
Duration: 00:06:279

Stderr:

#
# Fatal error in ../../src/hashmap.h, line 248
# Check failed: base::bits::IsPowerOfTwo32(capacity_).
#

==== C stack trace ===============================

Original issue's description:
> Canonicalize handles for optimized compilation.
>
> R=bmeurer@chromium.org
>
> Committed: https://crrev.com/15f36b2b1e166a511966a9991fddea94f890a755
> Cr-Commit-Position: refs/heads/master@{#31566}

TBR=jochen@chromium.org,bmeurer@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.chromium.org/1417013007

Cr-Commit-Position: refs/heads/master@{#31570}
2015-10-26 14:45:34 +00:00

160 lines
4.9 KiB
C++

// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/handles.h"
#include "src/base/logging.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
#ifdef DEBUG
bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const {
DCHECK_NOT_NULL(location_);
Object* object = *location_;
if (object->IsSmi()) return true;
HeapObject* heap_object = HeapObject::cast(object);
Heap* heap = heap_object->GetHeap();
Object** roots_array_start = heap->roots_array_start();
if (roots_array_start <= location_ &&
location_ < roots_array_start + Heap::kStrongRootListLength &&
heap->RootCanBeTreatedAsConstant(
static_cast<Heap::RootListIndex>(location_ - roots_array_start))) {
return true;
}
if (!AllowHandleDereference::IsAllowed()) return false;
if (mode == INCLUDE_DEFERRED_CHECK &&
!AllowDeferredHandleDereference::IsAllowed()) {
// Accessing cells, maps and internalized strings is safe.
if (heap_object->IsCell()) return true;
if (heap_object->IsMap()) return true;
if (heap_object->IsInternalizedString()) return true;
return !heap->isolate()->IsDeferredHandle(location_);
}
return true;
}
#endif
int HandleScope::NumberOfHandles(Isolate* isolate) {
HandleScopeImplementer* impl = isolate->handle_scope_implementer();
int n = impl->blocks()->length();
if (n == 0) return 0;
return ((n - 1) * kHandleBlockSize) + static_cast<int>(
(isolate->handle_scope_data()->next - impl->blocks()->last()));
}
Object** HandleScope::Extend(Isolate* isolate) {
HandleScopeData* current = isolate->handle_scope_data();
Object** result = current->next;
DCHECK(result == current->limit);
// Make sure there's at least one scope on the stack and that the
// top of the scope stack isn't a barrier.
if (!Utils::ApiCheck(current->level != 0,
"v8::HandleScope::CreateHandle()",
"Cannot create a handle without a HandleScope")) {
return NULL;
}
HandleScopeImplementer* impl = isolate->handle_scope_implementer();
// If there's more room in the last block, we use that. This is used
// for fast creation of scopes after scope barriers.
if (!impl->blocks()->is_empty()) {
Object** limit = &impl->blocks()->last()[kHandleBlockSize];
if (current->limit != limit) {
current->limit = limit;
DCHECK(limit - current->next < kHandleBlockSize);
}
}
// If we still haven't found a slot for the handle, we extend the
// current handle scope by allocating a new handle block.
if (result == current->limit) {
// If there's a spare block, use it for growing the current scope.
result = impl->GetSpareOrNewBlock();
// Add the extension to the global list of blocks, but count the
// extension as part of the current scope.
impl->blocks()->Add(result);
current->limit = &result[kHandleBlockSize];
}
return result;
}
void HandleScope::DeleteExtensions(Isolate* isolate) {
HandleScopeData* current = isolate->handle_scope_data();
isolate->handle_scope_implementer()->DeleteExtensions(current->limit);
}
#ifdef ENABLE_HANDLE_ZAPPING
void HandleScope::ZapRange(Object** start, Object** end) {
DCHECK(end - start <= kHandleBlockSize);
for (Object** p = start; p != end; p++) {
*reinterpret_cast<Address*>(p) = kHandleZapValue;
}
}
#endif
Address HandleScope::current_level_address(Isolate* isolate) {
return reinterpret_cast<Address>(&isolate->handle_scope_data()->level);
}
Address HandleScope::current_next_address(Isolate* isolate) {
return reinterpret_cast<Address>(&isolate->handle_scope_data()->next);
}
Address HandleScope::current_limit_address(Isolate* isolate) {
return reinterpret_cast<Address>(&isolate->handle_scope_data()->limit);
}
DeferredHandleScope::DeferredHandleScope(Isolate* isolate)
: impl_(isolate->handle_scope_implementer()) {
impl_->BeginDeferredScope();
HandleScopeData* data = impl_->isolate()->handle_scope_data();
Object** new_next = impl_->GetSpareOrNewBlock();
Object** new_limit = &new_next[kHandleBlockSize];
DCHECK(data->limit == &impl_->blocks()->last()[kHandleBlockSize]);
impl_->blocks()->Add(new_next);
#ifdef DEBUG
prev_level_ = data->level;
#endif
data->level++;
prev_limit_ = data->limit;
prev_next_ = data->next;
data->next = new_next;
data->limit = new_limit;
}
DeferredHandleScope::~DeferredHandleScope() {
impl_->isolate()->handle_scope_data()->level--;
DCHECK(handles_detached_);
DCHECK(impl_->isolate()->handle_scope_data()->level == prev_level_);
}
DeferredHandles* DeferredHandleScope::Detach() {
DeferredHandles* deferred = impl_->Detach(prev_limit_);
HandleScopeData* data = impl_->isolate()->handle_scope_data();
data->next = prev_next_;
data->limit = prev_limit_;
#ifdef DEBUG
handles_detached_ = true;
#endif
return deferred;
}
} // namespace internal
} // namespace v8