summaryrefslogtreecommitdiffstats
path: root/js/src/irregexp/RegExpShim.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/irregexp/RegExpShim.cpp')
-rw-r--r--js/src/irregexp/RegExpShim.cpp297
1 files changed, 297 insertions, 0 deletions
diff --git a/js/src/irregexp/RegExpShim.cpp b/js/src/irregexp/RegExpShim.cpp
new file mode 100644
index 0000000000..2b2c3cd4a0
--- /dev/null
+++ b/js/src/irregexp/RegExpShim.cpp
@@ -0,0 +1,297 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Copyright 2019 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 "irregexp/RegExpShim.h"
+
+#include "mozilla/MemoryReporting.h"
+
+#include <iostream>
+
+#include "irregexp/imported/regexp-macro-assembler.h"
+#include "irregexp/imported/regexp-stack.h"
+
+#include "vm/NativeObject-inl.h"
+
+namespace v8 {
+namespace internal {
+
+void PrintF(const char* format, ...) {
+ va_list arguments;
+ va_start(arguments, format);
+ vprintf(format, arguments);
+ va_end(arguments);
+}
+
+void PrintF(FILE* out, const char* format, ...) {
+ va_list arguments;
+ va_start(arguments, format);
+ vfprintf(out, format, arguments);
+ va_end(arguments);
+}
+
+StdoutStream::operator std::ostream&() const { return std::cerr; }
+
+template <typename T>
+std::ostream& StdoutStream::operator<<(T t) {
+ return std::cerr << t;
+}
+
+template std::ostream& StdoutStream::operator<<(char const* c);
+
+// Origin:
+// https://github.com/v8/v8/blob/855591a54d160303349a5f0a32fab15825c708d1/src/utils/ostreams.cc#L120-L169
+// (This is a hand-simplified version.)
+// Writes the given character to the output escaping everything outside
+// of printable ASCII range.
+std::ostream& operator<<(std::ostream& os, const AsUC16& c) {
+ base::uc16 v = c.value;
+ bool isPrint = 0x20 < v && v <= 0x7e;
+ char buf[10];
+ const char* format = isPrint ? "%c" : (v <= 0xFF) ? "\\x%02x" : "\\u%04x";
+ SprintfLiteral(buf, format, v);
+ return os << buf;
+}
+std::ostream& operator<<(std::ostream& os, const AsUC32& c) {
+ int32_t v = c.value;
+ if (v <= String::kMaxUtf16CodeUnit) {
+ return os << AsUC16(v);
+ }
+ char buf[13];
+ SprintfLiteral(buf, "\\u{%06x}", v);
+ return os << buf;
+}
+
+HandleScope::HandleScope(Isolate* isolate) : isolate_(isolate) {
+ isolate->openHandleScope(*this);
+}
+
+HandleScope::~HandleScope() {
+ isolate_->closeHandleScope(level_, non_gc_level_);
+}
+
+template <typename T>
+Handle<T>::Handle(T object, Isolate* isolate)
+ : location_(isolate->getHandleLocation(object.value())) {}
+
+template Handle<ByteArray>::Handle(ByteArray b, Isolate* isolate);
+template Handle<HeapObject>::Handle(const JS::Value& v, Isolate* isolate);
+template Handle<JSRegExp>::Handle(JSRegExp re, Isolate* isolate);
+template Handle<String>::Handle(String s, Isolate* isolate);
+
+template <typename T>
+Handle<T>::Handle(const JS::Value& value, Isolate* isolate)
+ : location_(isolate->getHandleLocation(value)) {
+ T::cast(Object(value)); // Assert that value has the correct type.
+}
+
+JS::Value* Isolate::getHandleLocation(const JS::Value& value) {
+ js::AutoEnterOOMUnsafeRegion oomUnsafe;
+ if (!handleArena_.Append(value)) {
+ oomUnsafe.crash("Irregexp handle allocation");
+ }
+ return &handleArena_.GetLast();
+}
+
+void* Isolate::allocatePseudoHandle(size_t bytes) {
+ PseudoHandle<void> ptr;
+ ptr.reset(js_malloc(bytes));
+ if (!ptr) {
+ return nullptr;
+ }
+ if (!uniquePtrArena_.Append(std::move(ptr))) {
+ return nullptr;
+ }
+ return uniquePtrArena_.GetLast().get();
+}
+
+template <typename T>
+PseudoHandle<T> Isolate::takeOwnership(void* ptr) {
+ PseudoHandle<T> result = maybeTakeOwnership<T>(ptr);
+ MOZ_ASSERT(result);
+ return result;
+}
+
+template <typename T>
+PseudoHandle<T> Isolate::maybeTakeOwnership(void* ptr) {
+ for (auto iter = uniquePtrArena_.IterFromLast(); !iter.Done(); iter.Prev()) {
+ auto& entry = iter.Get();
+ if (entry.get() == ptr) {
+ PseudoHandle<T> result;
+ result.reset(static_cast<T*>(entry.release()));
+ return result;
+ }
+ }
+ return PseudoHandle<T>();
+}
+
+PseudoHandle<ByteArrayData> ByteArray::maybeTakeOwnership(Isolate* isolate) {
+ PseudoHandle<ByteArrayData> result =
+ isolate->maybeTakeOwnership<ByteArrayData>(value().toPrivate());
+ setValue(JS::PrivateValue(nullptr));
+ return result;
+}
+
+PseudoHandle<ByteArrayData> ByteArray::takeOwnership(Isolate* isolate) {
+ PseudoHandle<ByteArrayData> result = maybeTakeOwnership(isolate);
+ MOZ_ASSERT(result);
+ return result;
+}
+
+void Isolate::trace(JSTracer* trc) {
+ js::gc::AssertRootMarkingPhase(trc);
+
+ for (auto iter = handleArena_.Iter(); !iter.Done(); iter.Next()) {
+ auto& elem = iter.Get();
+ JS::GCPolicy<JS::Value>::trace(trc, &elem, "Isolate handle arena");
+ }
+}
+
+size_t Isolate::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ size_t size = mallocSizeOf(this);
+
+ size += mallocSizeOf(regexpStack_);
+ size += ExternalReference::SizeOfExcludingThis(mallocSizeOf, regexpStack_);
+
+ size += handleArena_.SizeOfExcludingThis(mallocSizeOf);
+ size += uniquePtrArena_.SizeOfExcludingThis(mallocSizeOf);
+ return size;
+}
+
+/*static*/ Handle<String> String::Flatten(Isolate* isolate,
+ Handle<String> string) {
+ if (string->IsFlat()) {
+ return string;
+ }
+ js::AutoEnterOOMUnsafeRegion oomUnsafe;
+ JSLinearString* linear = string->str()->ensureLinear(isolate->cx());
+ if (!linear) {
+ oomUnsafe.crash("Irregexp String::Flatten");
+ }
+ return Handle<String>(JS::StringValue(linear), isolate);
+}
+
+// This is only used for trace messages printing the source pattern of
+// a regular expression. We have to return a unique_ptr, but we don't
+// care about the contents, so we return an empty null-terminated string.
+std::unique_ptr<char[]> String::ToCString() {
+ js::AutoEnterOOMUnsafeRegion oomUnsafe;
+
+ std::unique_ptr<char[]> ptr;
+ ptr.reset(static_cast<char*>(js_malloc(1)));
+ if (!ptr) {
+ oomUnsafe.crash("Irregexp String::ToCString");
+ }
+ ptr[0] = '\0';
+
+ return ptr;
+}
+
+bool Isolate::init() {
+ regexpStack_ = js_new<RegExpStack>();
+ if (!regexpStack_) {
+ return false;
+ }
+ return true;
+}
+
+Isolate::~Isolate() {
+ if (regexpStack_) {
+ js_delete(regexpStack_);
+ }
+}
+
+/* static */
+const void* ExternalReference::TopOfRegexpStack(Isolate* isolate) {
+ return reinterpret_cast<const void*>(
+ isolate->regexp_stack()->memory_top_address_address());
+}
+
+/* static */
+size_t ExternalReference::SizeOfExcludingThis(
+ mozilla::MallocSizeOf mallocSizeOf, RegExpStack* regexpStack) {
+ if (regexpStack->thread_local_.owns_memory_) {
+ return mallocSizeOf(regexpStack->thread_local_.memory_);
+ }
+ return 0;
+}
+
+Handle<ByteArray> Isolate::NewByteArray(int length, AllocationType alloc) {
+ MOZ_RELEASE_ASSERT(length >= 0);
+
+ js::AutoEnterOOMUnsafeRegion oomUnsafe;
+
+ size_t alloc_size = sizeof(uint32_t) + length;
+ ByteArrayData* data =
+ static_cast<ByteArrayData*>(allocatePseudoHandle(alloc_size));
+ if (!data) {
+ oomUnsafe.crash("Irregexp NewByteArray");
+ }
+ data->length = length;
+
+ return Handle<ByteArray>(JS::PrivateValue(data), this);
+}
+
+Handle<FixedArray> Isolate::NewFixedArray(int length) {
+ MOZ_RELEASE_ASSERT(length >= 0);
+ js::AutoEnterOOMUnsafeRegion oomUnsafe;
+ js::ArrayObject* array = js::NewDenseFullyAllocatedArray(cx(), length);
+ if (!array) {
+ oomUnsafe.crash("Irregexp NewFixedArray");
+ }
+ array->ensureDenseInitializedLength(0, length);
+ return Handle<FixedArray>(JS::ObjectValue(*array), this);
+}
+
+template <typename T>
+Handle<FixedIntegerArray<T>> Isolate::NewFixedIntegerArray(uint32_t length) {
+ MOZ_RELEASE_ASSERT(length < std::numeric_limits<uint32_t>::max() / sizeof(T));
+ js::AutoEnterOOMUnsafeRegion oomUnsafe;
+
+ uint32_t rawLength = length * sizeof(T);
+ size_t allocSize = sizeof(ByteArrayData) + rawLength;
+ ByteArrayData* data =
+ static_cast<ByteArrayData*>(allocatePseudoHandle(allocSize));
+ if (!data) {
+ oomUnsafe.crash("Irregexp NewFixedIntegerArray");
+ }
+ data->length = rawLength;
+
+ return Handle<FixedIntegerArray<T>>(JS::PrivateValue(data), this);
+}
+
+template <typename T>
+Handle<FixedIntegerArray<T>> FixedIntegerArray<T>::New(Isolate* isolate,
+ uint32_t length) {
+ return isolate->NewFixedIntegerArray<T>(length);
+}
+
+template class FixedIntegerArray<uint16_t>;
+
+template <typename CharT>
+Handle<String> Isolate::InternalizeString(
+ const base::Vector<const CharT>& str) {
+ js::AutoEnterOOMUnsafeRegion oomUnsafe;
+ JSAtom* atom = js::AtomizeChars(cx(), str.begin(), str.length());
+ if (!atom) {
+ oomUnsafe.crash("Irregexp InternalizeString");
+ }
+ return Handle<String>(JS::StringValue(atom), this);
+}
+
+template Handle<String> Isolate::InternalizeString(
+ const base::Vector<const uint8_t>& str);
+template Handle<String> Isolate::InternalizeString(
+ const base::Vector<const char16_t>& str);
+
+static_assert(JSRegExp::RegistersForCaptureCount(JSRegExp::kMaxCaptures) <=
+ RegExpMacroAssembler::kMaxRegisterCount);
+
+} // namespace internal
+} // namespace v8