Index: src/elements.cc |
diff --git a/src/elements.cc b/src/elements.cc |
index 5b454e5964ae2caf873f30adc7ddc83b1f6f08c8..6459279dea56753cbbdfa194678d77c0cb6b11ea 100644 |
--- a/src/elements.cc |
+++ b/src/elements.cc |
@@ -30,7 +30,7 @@ |
#include "objects.h" |
#include "elements.h" |
#include "utils.h" |
- |
+#include "v8conversions.h" |
// Each concrete ElementsAccessor can handle exactly one ElementsKind, |
// several abstract ElementsAccessor classes are used to allow sharing |
@@ -483,6 +483,63 @@ static void CopyDictionaryToDoubleElements(FixedArrayBase* from_base, |
} |
+static void TraceTopFrame() { |
+ StackFrameIterator it; |
+ if (it.done()) { |
+ PrintF("unknown location (no JavaScript frames present)"); |
+ return; |
+ } |
+ StackFrame* raw_frame = it.frame(); |
+ if (raw_frame->is_internal()) { |
+ Isolate* isolate = Isolate::Current(); |
+ Code* apply_builtin = isolate->builtins()->builtin( |
+ Builtins::kFunctionApply); |
+ if (raw_frame->unchecked_code() == apply_builtin) { |
+ PrintF("apply from "); |
+ it.Advance(); |
+ raw_frame = it.frame(); |
+ } |
+ } |
+ JavaScriptFrame::PrintTop(stdout, false, true); |
+} |
+ |
+ |
+void CheckArrayAbuse(JSObject* obj, const char* op, uint32_t key) { |
+ Object* raw_length = NULL; |
+ const char* elements_type = "array"; |
+ if (obj->IsJSArray()) { |
+ JSArray* array = JSArray::cast(obj); |
+ raw_length = array->length(); |
+ } else { |
+ raw_length = Smi::FromInt(obj->elements()->length()); |
+ elements_type = "object"; |
+ } |
+ |
+ if (raw_length->IsNumber()) { |
+ double n = raw_length->Number(); |
+ if (FastI2D(FastD2UI(n)) == n) { |
+ int32_t int32_length = DoubleToInt32(n); |
+ if (key >= static_cast<uint32_t>(int32_length)) { |
+ PrintF("[OOB %s %s (%s length = %d, element accessed = %d) in ", |
+ elements_type, op, elements_type, |
+ static_cast<int>(int32_length), |
+ static_cast<int>(key)); |
+ TraceTopFrame(); |
+ PrintF("]\n"); |
+ } |
+ } else { |
+ PrintF("[%s elements length not integer value in ", elements_type); |
+ TraceTopFrame(); |
+ PrintF("]\n"); |
+ } |
+ } else { |
+ PrintF("[%s elements length not a number in ", elements_type); |
+ TraceTopFrame(); |
+ PrintF("]\n"); |
+ } |
+} |
+ |
+ |
// Base class for element handler implementations. Contains the |
// the common logic for objects with different ElementsKinds. |
// Subclasses must specialize method for which the element |
@@ -570,6 +627,11 @@ class ElementsAccessorBase : public ElementsAccessor { |
if (backing_store == NULL) { |
backing_store = holder->elements(); |
} |
+ |
+ if (FLAG_trace_array_abuse) { |
+ CheckArrayAbuse(holder, "element read", key); |
+ } |
+ |
return ElementsAccessorSubclass::GetImpl( |
receiver, holder, key, backing_store); |
} |