Browse Source

LibJS+AK: Move cross-platform stack bounds code from JS::Heap to AK::StackInfo

This will be useful for other things than the Heap, maybe even outside
of LibJS.
Linus Groh 4 years ago
parent
commit
9c3ead8f91
5 changed files with 136 additions and 40 deletions
  1. 2 0
      AK/Forward.h
  2. 72 0
      AK/StackInfo.cpp
  3. 54 0
      AK/StackInfo.h
  4. 3 40
      Libraries/LibJS/Heap/Heap.cpp
  5. 5 0
      Libraries/LibJS/Runtime/VM.h

+ 2 - 0
AK/Forward.h

@@ -39,6 +39,7 @@ class JsonObject;
 class JsonValue;
 class LogStream;
 class SharedBuffer;
+class StackInfo;
 class String;
 class StringBuilder;
 class StringImpl;
@@ -160,6 +161,7 @@ using AK::RefPtr;
 using AK::SharedBuffer;
 using AK::SinglyLinkedList;
 using AK::Span;
+using AK::StackInfo;
 using AK::String;
 using AK::StringBuilder;
 using AK::StringImpl;

+ 72 - 0
AK/StackInfo.cpp

@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020, the SerenityOS developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/Assertions.h>
+#include <AK/StackInfo.h>
+#include <stdio.h>
+
+#ifdef __serenity__
+#    include <serenity.h>
+#elif __linux__ or __APPLE__
+#    include <pthread.h>
+#endif
+
+namespace AK {
+
+StackInfo::StackInfo()
+{
+#ifdef __serenity__
+    if (get_stack_bounds(&m_base, &m_size) < 0) {
+        perror("get_stack_bounds");
+        ASSERT_NOT_REACHED();
+    }
+#elif __linux__
+    pthread_attr_t attr = {};
+    if (int rc = pthread_getattr_np(pthread_self(), &attr) != 0) {
+        fprintf(stderr, "pthread_getattr_np: %s\n", strerror(-rc));
+        ASSERT_NOT_REACHED();
+    }
+    if (int rc = pthread_attr_getstack(&attr, (void**)&m_base, &m_size) != 0) {
+        fprintf(stderr, "pthread_attr_getstack: %s\n", strerror(-rc));
+        ASSERT_NOT_REACHED();
+    }
+    pthread_attr_destroy(&attr);
+#elif __APPLE__
+    m_base = (FlatPtr)pthread_get_stackaddr_np(pthread_self());
+    pthread_attr_t attr = {};
+    if (int rc = pthread_attr_getstacksize(&attr, &m_size) != 0) {
+        fprintf(stderr, "pthread_attr_getstacksize: %s\n", strerror(-rc));
+        ASSERT_NOT_REACHED();
+    }
+    pthread_attr_destroy(&attr);
+#else
+    ASSERT_NOT_REACHED();
+#endif
+
+    m_top = m_base + m_size;
+}
+
+}

+ 54 - 0
AK/StackInfo.h

@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020, the SerenityOS developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+
+namespace AK {
+
+class StackInfo {
+public:
+    StackInfo();
+
+    FlatPtr base() const { return m_base; }
+    FlatPtr top() const { return m_top; }
+    size_t size() const { return m_size; }
+    size_t size_free() const
+    {
+        FlatPtr dummy;
+        return reinterpret_cast<FlatPtr>(&dummy) - m_base;
+    }
+
+private:
+    FlatPtr m_base;
+    FlatPtr m_top;
+    size_t m_size;
+};
+
+}
+
+using AK::StackInfo;

+ 3 - 40
Libraries/LibJS/Heap/Heap.cpp

@@ -26,6 +26,7 @@
 
 #include <AK/Badge.h>
 #include <AK/HashTable.h>
+#include <AK/StackInfo.h>
 #include <AK/TemporaryChange.h>
 #include <LibCore/ElapsedTimer.h>
 #include <LibJS/Heap/Allocator.h>
@@ -35,17 +36,8 @@
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Object.h>
 #include <setjmp.h>
-#include <stdio.h>
 
-#ifdef __serenity__
-#    include <serenity.h>
-#elif __linux__ or __APPLE__
-#    include <pthread.h>
-#endif
-
-#ifdef __serenity__
 //#define HEAP_DEBUG
-#endif
 
 namespace JS {
 
@@ -151,39 +143,10 @@ void Heap::gather_conservative_roots(HashTable<Cell*>& roots)
     for (size_t i = 0; i < ((size_t)sizeof(buf)) / sizeof(FlatPtr); i += sizeof(FlatPtr))
         possible_pointers.set(raw_jmp_buf[i]);
 
-    FlatPtr stack_base;
-    size_t stack_size;
-
-#ifdef __serenity__
-    if (get_stack_bounds(&stack_base, &stack_size) < 0) {
-        perror("get_stack_bounds");
-        ASSERT_NOT_REACHED();
-    }
-#elif __linux__
-    pthread_attr_t attr = {};
-    if (int rc = pthread_getattr_np(pthread_self(), &attr) != 0) {
-        fprintf(stderr, "pthread_getattr_np: %s\n", strerror(-rc));
-        ASSERT_NOT_REACHED();
-    }
-    if (int rc = pthread_attr_getstack(&attr, (void**)&stack_base, &stack_size) != 0) {
-        fprintf(stderr, "pthread_attr_getstack: %s\n", strerror(-rc));
-        ASSERT_NOT_REACHED();
-    }
-    pthread_attr_destroy(&attr);
-#elif __APPLE__
-    stack_base = (FlatPtr)pthread_get_stackaddr_np(pthread_self());
-    pthread_attr_t attr = {};
-    if (int rc = pthread_attr_getstacksize(&attr, &stack_size) != 0) {
-        fprintf(stderr, "pthread_attr_getstacksize: %s\n", strerror(-rc));
-        ASSERT_NOT_REACHED();
-    }
-    pthread_attr_destroy(&attr);
-#endif
-
     FlatPtr stack_reference = reinterpret_cast<FlatPtr>(&dummy);
-    FlatPtr stack_top = stack_base + stack_size;
+    auto& stack_info = m_vm.stack_info();
 
-    for (FlatPtr stack_address = stack_reference; stack_address < stack_top; stack_address += sizeof(FlatPtr)) {
+    for (FlatPtr stack_address = stack_reference; stack_address < stack_info.top(); stack_address += sizeof(FlatPtr)) {
         auto data = *reinterpret_cast<FlatPtr*>(stack_address);
         possible_pointers.set(data);
     }

+ 5 - 0
Libraries/LibJS/Runtime/VM.h

@@ -29,6 +29,7 @@
 #include <AK/FlyString.h>
 #include <AK/HashMap.h>
 #include <AK/RefCounted.h>
+#include <AK/StackInfo.h>
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Runtime/CommonPropertyNames.h>
 #include <LibJS/Runtime/ErrorTypes.h>
@@ -165,6 +166,8 @@ public:
     Value last_value() const { return m_last_value; }
     void set_last_value(Badge<Interpreter>, Value value) { m_last_value = value; }
 
+    const StackInfo& stack_info() const { return m_stack_info; };
+
     bool underscore_is_last_value() const { return m_underscore_is_last_value; }
     void set_underscore_is_last_value(bool b) { m_underscore_is_last_value = b; }
 
@@ -248,6 +251,8 @@ private:
     ScopeType m_unwind_until { ScopeType::None };
     FlyString m_unwind_until_label;
 
+    StackInfo m_stack_info;
+
     bool m_underscore_is_last_value { false };
 
     HashMap<String, Symbol*> m_global_symbol_map;