diff --git a/mruby/.github/labeler.yml b/mruby/.github/labeler.yml
index 742fc2b3..bdd33ca7 100644
--- a/mruby/.github/labeler.yml
+++ b/mruby/.github/labeler.yml
@@ -7,11 +7,17 @@ build:
- any:
- changed-files:
- any-glob-to-any-file:
+ - Dockerfile
- Makefile
- Rakefile
+ - appveyor.yml
+ - build_config.rb
- build_config/**/*
+ - docker-compose.yml
- lib/**/*
+ - minirake
- tasks/**/*
+ - .travis.yml
core:
- any:
- changed-files:
diff --git a/mruby/.github/linters/.yaml-lint.yml b/mruby/.github/linters/.yaml-lint.yml
index be4c8879..f5e0ee46 100644
--- a/mruby/.github/linters/.yaml-lint.yml
+++ b/mruby/.github/linters/.yaml-lint.yml
@@ -4,6 +4,8 @@
extends: default
rules:
+ comments:
+ min-spaces-from-content: 1
document-start: disable
line-length: disable
truthy: false
diff --git a/mruby/.github/workflows/lint.yml b/mruby/.github/workflows/lint.yml
index b95005f2..6f92b31d 100644
--- a/mruby/.github/workflows/lint.yml
+++ b/mruby/.github/workflows/lint.yml
@@ -19,7 +19,7 @@ jobs:
pip install pre-commit
- name: Set PY
run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
- - uses: actions/cache@v3
+ - uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
diff --git a/mruby/.github/workflows/oss-fuzz.yml b/mruby/.github/workflows/oss-fuzz.yml
index 72d40cf9..c4e0b3d1 100644
--- a/mruby/.github/workflows/oss-fuzz.yml
+++ b/mruby/.github/workflows/oss-fuzz.yml
@@ -11,16 +11,16 @@ jobs:
- name: Build Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
- oss-fuzz-project-name: 'mruby'
+ oss-fuzz-project-name: "mruby"
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
- oss-fuzz-project-name: 'mruby'
+ oss-fuzz-project-name: "mruby"
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: failure()
with:
name: artifacts
diff --git a/mruby/.github/workflows/super-linter.yml b/mruby/.github/workflows/super-linter.yml
index 8d817ef4..054b12f1 100644
--- a/mruby/.github/workflows/super-linter.yml
+++ b/mruby/.github/workflows/super-linter.yml
@@ -9,8 +9,8 @@ permissions:
jobs:
build:
permissions:
- contents: read # for actions/checkout to fetch code
- statuses: write # for github/super-linter/slim to mark status of each linter run
+ contents: read # for actions/checkout to fetch code
+ statuses: write # for github/super-linter/slim to mark status of each linter run
name: Lint Code Base
runs-on: ubuntu-latest
steps:
@@ -20,9 +20,8 @@ jobs:
# Full git history is needed to get a proper list of changed files within `super-linter`
fetch-depth: 0
- name: Lint Code Base
- uses: super-linter/super-linter/slim@v5.7.2
+ uses: super-linter/super-linter/slim@v6.0.0
env:
- ERROR_ON_MISSING_EXEC_BIT: true
VALIDATE_BASH: true
# VALIDATE_BASH_EXEC: true
# VALIDATE_EDITORCONFIG: true
diff --git a/mruby/.gitignore b/mruby/.gitignore
index eb5b5ddf..e604347b 100644
--- a/mruby/.gitignore
+++ b/mruby/.gitignore
@@ -31,5 +31,6 @@ compile_commands.json
compile_flags.txt
cscope.files
cscope.out
+node_modules
tags
!Gemfile.lock
diff --git a/mruby/.pre-commit-config.yaml b/mruby/.pre-commit-config.yaml
index 6e0b6024..4f8b9c48 100644
--- a/mruby/.pre-commit-config.yaml
+++ b/mruby/.pre-commit-config.yaml
@@ -3,7 +3,7 @@ default_stages: [commit, push]
default_language_version:
# force all unspecified Python hooks to run python3
python: python3
-minimum_pre_commit_version: '2.18.1'
+minimum_pre_commit_version: "2.18.1"
repos:
- repo: meta
hooks:
@@ -20,6 +20,8 @@ repos:
- id: check-shebang-scripts-are-executable
- id: check-vcs-permalinks
- id: check-yaml
+ - id: detect-aws-credentials
+ args: [--allow-missing-credentials]
- id: detect-private-key
- id: end-of-file-fixer
- id: file-contents-sorter
@@ -35,7 +37,7 @@ repos:
- id: forbid-tabs
exclude: Makefile$|Makefile\..+$|makefile$|\.mk$
- id: remove-tabs
- args: [--whitespaces-count, '2']
+ args: [--whitespaces-count, "2"]
exclude: Makefile$|Makefile\..+$|makefile$|\.mk$
- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
@@ -50,8 +52,13 @@ repos:
- id: script-must-not-have-extension
name: Local policy is to exclude extension from all shell files
types: [shell]
+ - repo: https://github.com/pre-commit/mirrors-prettier
+ rev: v4.0.0-alpha.8
+ hooks:
+ - id: prettier
+ exclude: ^doc/internal/opcode\.md$
- repo: https://github.com/igorshubovych/markdownlint-cli
- rev: v0.37.0
+ rev: v0.38.0
hooks:
- id: markdownlint
name: Run markdownlint
diff --git a/mruby/.prettierrc b/mruby/.prettierrc
new file mode 100644
index 00000000..81b81d20
--- /dev/null
+++ b/mruby/.prettierrc
@@ -0,0 +1,3 @@
+{
+ "bracketSpacing": false
+}
diff --git a/mruby/AUTHORS b/mruby/AUTHORS
index a3016325..3464d367 100644
--- a/mruby/AUTHORS
+++ b/mruby/AUTHORS
@@ -1,10 +1,10 @@
# Authors of mruby (mruby developers)
-## The List of Contributors sorted by number of commits (as of 2023-11-20 6a3a810)
+## The List of Contributors sorted by number of commits (as of 2024-02-10 d2af9da)
- 9408 Yukihiro "Matz" Matsumoto (@matz)*
+ 9592 Yukihiro "Matz" Matsumoto (@matz)*
586 KOBAYASHI Shuji (@shuujii)
- 508 dearblue (@dearblue)*
+ 547 dearblue (@dearblue)*
378 Daniel Bovensiepen (@bovi)*
346 Takeshi Watanabe (@take-cheeze)*
334 Masaki Muranaka (@monaka)
@@ -12,7 +12,7 @@
234 Jun Hiroe (@suzukaze)
220 Cremno (@cremno)*
209 Yuki Kurihara (@ksss)+
- 165 John Bampton (@jbampton)
+ 170 John Bampton (@jbampton)
151 Yasuhiro Matsumoto (@mattn)*
113 Carson McDonald (@carsonmcdonald)
103 Tomasz Dąbrowski (@dabroz)*
@@ -82,6 +82,7 @@
7 Bhargava Shastry (@bshastry)*
7 Kouichi Nakanishi (@keizo042)
7 Rubyist (@expeditiousRubyist)
+ 7 SiZiOUS (@sizious)
7 Simon Génier (@simon-shopify)
7 Terence Lee (@hone)
7 Wataru Ashihara (@wataash)*
@@ -105,7 +106,6 @@
5 Keita Obo (@ktaobo)*
5 Max Anselm (@silverhammermba)
5 Rodrigo Malizia (@rmalizia44)+
- 5 SiZiOUS (@sizious)
5 Syohei YOSHIDA (@syohex)
5 TOMITA Masahiro (@tmtm)
5 Yurie Yamane (@yurie)+
@@ -156,6 +156,7 @@
3 bamchoh (@bamchoh)
3 sasaki takeru (@takeru)
3 windwiny (@windwiny)
+ 3 星湖新 (@hoshiumiarata)
2 Akira Moroo (@retrage)
2 Artur K (@nemerle)
2 Christian Mauceri (@mauceri)
@@ -290,6 +291,7 @@
1 Yusuke Tanaka (@csouls)
1 alpha.netzilla (@alpha-netzilla)
1 arton (@arton)
+ 1 buty4649 (@buty4649)
1 duangsuse (@duangsuse)
1 fl0l0u (@fl0l0u)
1 hhc0null (@hhc0null)
diff --git a/mruby/Doxyfile b/mruby/Doxyfile
index 3a66c141..2df76d8c 100644
--- a/mruby/Doxyfile
+++ b/mruby/Doxyfile
@@ -48,7 +48,7 @@ PROJECT_NAME = mruby
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 3.2.0
+PROJECT_NUMBER = 3.3.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
diff --git a/mruby/LEGAL b/mruby/LEGAL
index 24c8dc67..116a218f 100644
--- a/mruby/LEGAL
+++ b/mruby/LEGAL
@@ -4,10 +4,41 @@ LEGAL NOTICE INFORMATION
All the files in this distribution are covered under the MIT license
(see the file LICENSE) except some files mentioned below:
+- src/string.c: mrb_memsearch_ss() is based on 2 clause BSD license code by Wojciech Muła (@WojciechMula)
- src/readfloat.c: public domain by Yasuhiro Matsumoto (@mattn)
- src/fmt_fp.c: public domain by Dave Hylands (@dhylands)
- mrbgems/mruby-dir/src/Win/dirent.c: MIT-like license by Kevlin Henney
+[src/string.c]
+The implementation of mrb_memsearch_ss() is taken from
+https://github.com/WojciechMula/sse4-strstr.git
+
+Copyright (c) 2008-2016, Wojciech Muła
+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.
+
[src/readfloat.c]
strtod implementation.
diff --git a/mruby/NEWS b/mruby/NEWS
index 36f955eb..7144b3a8 100644
--- a/mruby/NEWS
+++ b/mruby/NEWS
@@ -1,63 +1,189 @@
NEWS
----
-# User visible changes in `mruby3.2`
+# User visible changes in `mruby3.3` from `mruby3.2`
-# The language
-
-- Now `a::B = c` should evaluate `a` then `c`.
-- Anonymous arguments `*`, `**`, `&` can be passed for forwarding.
-- Multi-precision integer is available now via `mruby-bigint` gem.
-
-# mruby VM and bytecode
-
-- `OP_ARYDUP` was renamed to `OP_ARYSPLAT`. The instruction name
- was changed but instruction number and basic behavior have not
- changed (except that `ARYDUP nil` makes `[]`).
-
-# Tools
-
-## `mruby`
-
-- `-b` only specifies the script is the binary. The files loaded by `-r` are not affected by the option.
-- `mruby` now loads complied binary if the suffix is `.mrb`.
-
-## `mrbc`
+"**_NOTE_**:" are changes to be aware of.
-- Add `--no-optimize` option to disable optimization.
-
-# mrbgems
-
-## mruby-class-ext
-
-- Add `Class#subclasses` method.
-- Add `Module#undefined_instance_methods` method.
-
-## New bundled gems
-
-- mruby-errno from [https://github.com/iij/mruby-errno.git]
-- mruby-set from [https://github.com/yui-knk/mruby-set.git]
-- mruby-dir from [https://github.com/iij/mruby-dir.git]
-
-# CVEs
-
-Following CVEs are fixed.
+# The language
-- [CVE-2022-0080](https://nvd.nist.gov/vuln/detail/CVE-2022-0080)
-- [CVE-2022-0240](https://nvd.nist.gov/vuln/detail/CVE-2022-0240)
-- [CVE-2022-0326](https://nvd.nist.gov/vuln/detail/CVE-2022-0326)
-- [CVE-2022-0481](https://nvd.nist.gov/vuln/detail/CVE-2022-0481)
-- [CVE-2022-0525](https://nvd.nist.gov/vuln/detail/CVE-2022-0525)
-- [CVE-2022-0570](https://nvd.nist.gov/vuln/detail/CVE-2022-0570)
-- [CVE-2022-0614](https://nvd.nist.gov/vuln/detail/CVE-2022-0614)
-- [CVE-2022-0623](https://nvd.nist.gov/vuln/detail/CVE-2022-0623)
-- [CVE-2022-0630](https://nvd.nist.gov/vuln/detail/CVE-2022-0630)
-- [CVE-2022-0631](https://nvd.nist.gov/vuln/detail/CVE-2022-0631)
-- [CVE-2022-0632](https://nvd.nist.gov/vuln/detail/CVE-2022-0632)
-- [CVE-2022-0717](https://nvd.nist.gov/vuln/detail/CVE-2022-0717)
-- [CVE-2022-0890](https://nvd.nist.gov/vuln/detail/CVE-2022-0890)
-- [CVE-2022-1106](https://nvd.nist.gov/vuln/detail/CVE-2022-1106)
-- [CVE-2022-1212](https://nvd.nist.gov/vuln/detail/CVE-2022-1212)
-- [CVE-2022-1276](https://nvd.nist.gov/vuln/detail/CVE-2022-1276)
-- [CVE-2022-1286](https://nvd.nist.gov/vuln/detail/CVE-2022-1286)
-- [CVE-2022-1934](https://nvd.nist.gov/vuln/detail/CVE-2022-1934)
+- aliases work properly with `super` ([2ad3f0e](https://github.com/mruby/mruby/commit/2ad3f0e))
+- `callee` method work differently with aliases in mruby ([f2dc76e](https://github.com/mruby/mruby/commit/f2dc76e))
+- define `Kernel#respond_to_missing?` method ([347586e](https://github.com/mruby/mruby/commit/347586e))
+- `_inspect` method (`inspect` with recursive check) is removed
+ ([e2bbf75](https://github.com/mruby/mruby/commit/e2bbf75), [5cb0c74](https://github.com/mruby/mruby/commit/5cb0c74), [113565a](https://github.com/mruby/mruby/commit/113565a),
+ [0713f2a](https://github.com/mruby/mruby/commit/0713f2a), [6ae6b63](https://github.com/mruby/mruby/commit/6ae6b63), [fc9fffc](https://github.com/mruby/mruby/commit/fc9fffc))
+- `__printstr__` method is removed; use `print` instead
+ ([acecee0](https://github.com/mruby/mruby/commit/acecee0), [192e6e3](https://github.com/mruby/mruby/commit/192e6e3))
+- New method `String#bytesplice` ([5274647](https://github.com/mruby/mruby/commit/5274647), [a2e2e83](https://github.com/mruby/mruby/commit/a2e2e83))
+- Allow `return` in blocks to cross C boundaries ([#6125](https://github.com/mruby/mruby/pull/6125))
+
+# Configuration
+
+- mruby can be built using Docker now. Try `docker-compose build` for example. ([#5961](https://github.com/mruby/mruby/pull/5961))
+- New Platform: DJGPP (MS-DOS) ([#6022](https://github.com/mruby/mruby/pull/6022))
+- New Platform: Nintendo Wii ([#6086](https://github.com/mruby/mruby/pull/6086))
+- Improved Platform: Android ([#6013](https://github.com/mruby/mruby/pull/6013))
+- Improved Platform: Dreamcast ([#6130](https://github.com/mruby/mruby/pull/6130))
+- Allow tests to be disabled for specific gems; warn about disabled tests ([#6012](https://github.com/mruby/mruby/pull/6012))
+- Replace `MRB_NO_DIRECT_THREADING` with `MRB_USE_VM_SWITCH_DISPATCH` ([#5902](https://github.com/mruby/mruby/pull/5902))
+
+# mruby memory API
+
+- `mrb_default_allocf` can be overridden by the application ([34c5d96](https://github.com/mruby/mruby/commit/34c5d96))
+- `mrb_open_allocf` will be deprecated ([cfee5c2](https://github.com/mruby/mruby/commit/cfee5c2))
+
+# Changes in C API
+
+- add new error handling API functions ([8c8bbd9](https://github.com/mruby/mruby/commit/8c8bbd9))
+- Add `mrb_vm_ci_env_clear()` function with `MRB_API` ([#5945](https://github.com/mruby/mruby/pull/5945))
+- a new function `mrb_check_frozen_value()` ([ccdf75c](https://github.com/mruby/mruby/commit/ccdf75c))
+- avoid formatting in `mrb_bug()` ([82a48bd](https://github.com/mruby/mruby/commit/82a48bd))
+ **_NOTE_**: If you are using it, you must give a simple string or replace it with a call to `mrb_raise()` series.
+- stop using `mrbc_` prefix for compiler context ([c5e3cbe](https://github.com/mruby/mruby/commit/c5e3cbe))
+ The same names are provided as before, but we recommend replacing them.
+- Allow `Class#allocate` to be prohibited
+ ([#5979](https://github.com/mruby/mruby/pull/5979), [#6122](https://github.com/mruby/mruby/pull/6122), [#6123](https://github.com/mruby/mruby/pull/6123))
+ To disable `#allocate`, use `MRB_UNDEF_ALLOCATOR()`.
+ This is also automatically applied when the subclass is created, but to explicitly allow it, use `MRB_DEFINE_ALLOCATOR()`.
+
+# Changes in mrbgems
+
+- **default.gembox**: Add mruby debugger mrdb (`mruby-bin-debugger`) ([#5966](https://github.com/mruby/mruby/pull/5966))
+- **mruby-bin-config**: new options `--cxx`, `--cxxflags`, `--as`, `--asflags`, `--objc`, `--objcflags` ([#6054](https://github.com/mruby/mruby/pull/6054))
+- **mruby-binding**: renamed from `mruby-binding-core` of mruby3.2 ([11af5db](https://github.com/mruby/mruby/commit/11af5db))
+ **_NOTE_**: If using `mruby-binding-core` of mruby 3.2, replace it with `mruby-binding`.
+- **mruby-binding**: implemented `Binding#initialize_copy` method ([#5517](https://github.com/mruby/mruby/pull/5517))
+- **mruby-binding**: `Kernel#binding` responds only to calls from Ruby ([#5981](https://github.com/mruby/mruby/pull/5981))
+- **mruby-compar-ext**: Comparable#clamp to accept nil as arguments ([836bebc](https://github.com/mruby/mruby/commit/836bebc))
+- **mruby-compiler**: add print name for identifier tokens ([d7b2e3a](https://github.com/mruby/mruby/commit/d7b2e3a))
+- **mruby-data**: allow empty Data ([927a9df](https://github.com/mruby/mruby/commit/927a9df))
+- **mruby-enumerator**: remove internal attribute methods `obj`, `args`, `kwd`, `meth`, `fib`. ([735fa24](https://github.com/mruby/mruby/commit/735fa24))
+- **mruby-enumerator**: add Enumerator#size ([861f8bd](https://github.com/mruby/mruby/commit/861f8bd))
+- **mruby-eval**: merged `mruby-binding` of mruby3.2 ([501b22a](https://github.com/mruby/mruby/commit/501b22a), [#5989](https://github.com/mruby/mruby/pull/5989))
+ **_NOTE_**: If using `mruby-binding` of mruby 3.2, replace it with `mruby-eval`.
+- **mruby-fiber**: Add a new `mrb_fiber_new()` with `MRB_API` ([#6097](https://github.com/mruby/mruby/pull/6097))
+- **mruby-fiber**: Allows calling `Fiber#resume` from C ([#6106](https://github.com/mruby/mruby/pull/6106))
+- **mruby-fiber**: `Fiber#to_s` format changed ([#6105](https://github.com/mruby/mruby/pull/6105))
+- **mruby-io**: add File#atime and File#ctime ([321cfe9](https://github.com/mruby/mruby/commit/321cfe9))
+- **mruby-io**: Add "x" mode option for `IO.open` ([#6081](https://github.com/mruby/mruby/pull/6081))
+- **mruby-io**: File.new should not take blocks ([53de964](https://github.com/mruby/mruby/commit/53de964))
+- **mruby-method**: `Method#to_s` format changed ([f5bc82f](https://github.com/mruby/mruby/commit/f5bc82f), [02f189c](https://github.com/mruby/mruby/commit/02f189c))
+- **mruby-numeric-ext**: `int.pow(n,m)` to take bigint as exponential ([d482eab](https://github.com/mruby/mruby/commit/d482eab))
+- **mruby-pack**: support new directives `j`, `J`, `b`, `B`, `#`
+ ([2a1e3a5](https://github.com/mruby/mruby/commit/2a1e3a5), [e7021f1](https://github.com/mruby/mruby/commit/e7021f1), [e17f325](https://github.com/mruby/mruby/commit/e17f325))
+- **mruby-range-ext**: new method `Range#overlap?` ([384d0e2](https://github.com/mruby/mruby/commit/384d0e2))
+- **mruby-string-ext**: Add `String#valid_encoding?` method ([eabe2d9](https://github.com/mruby/mruby/commit/eabe2d9))
+- **mruby-struct**: allow empty Struct when a name is not given ([c212ede](https://github.com/mruby/mruby/commit/c212ede))
+- **mruby-time**: should allow year before 1900 ([e5de08b](https://github.com/mruby/mruby/commit/e5de08b))
+- **mruby-time**: support bigint to time_t if necessary ([7096d27](https://github.com/mruby/mruby/commit/7096d27))
+- **mruby-time**: need to handle negative time_t ([b064d7e](https://github.com/mruby/mruby/commit/b064d7e))
+
+# Changes in build system
+
+- Extended `rake install` task ([#5928](https://github.com/mruby/mruby/pull/5928))
+ **_NOTE_**: Due to this impact, executable files in the `mruby/bin/` directory by default are now symbolic links (batch files on Windows).
+ If previously relied on those executables, should be replaced with direct references to the entity created under the build directory (e.g. `mruby/build/host/bin/`).
+- Encode and decode escape characters for presym ([#6011](https://github.com/mruby/mruby/pull/6011))
+- Rakefile: remove default build target directories in `deep_clean` ([#6032](https://github.com/mruby/mruby/pull/6032), [1e38569](https://github.com/mruby/mruby/commit/1e38569))
+
+# Other breaking changes
+
+- `mrb_f_raise()` is now an internal function
+ ([#5923](https://github.com/mruby/mruby/pull/5923), [#6070](https://github.com/mruby/mruby/pull/6070))
+- `mrb_make_exception()` is now an internal function with different parameters
+ ([431f83e](https://github.com/mruby/mruby/commit/431f83e), [78137f3](https://github.com/mruby/mruby/commit/78137f3))
+- The `File#path` method no longer uses the `#to_path` method for implicit conversion
+ ([d86c4a7](https://github.com/mruby/mruby/commit/d86c4a7))
+- stop mrb isolation for each test file ([a20fbe5](https://github.com/mruby/mruby/commit/a20fbe5))
+- RBreak remembers the CI location ([#6103](https://github.com/mruby/mruby/pull/6103))
+
+# Bugs Fixed
+
+- [#5724](https://github.com/mruby/mruby/issues/5724) Rational#\*\* is missing
+- [#5725](https://github.com/mruby/mruby/issues/5725) weird const_missing exceptions in mrblib code
+- [#5789](https://github.com/mruby/mruby/issues/5789) No memory release of backtrace information due to stack error
+- [#5932](https://github.com/mruby/mruby/issues/5932) How to create a block using the C API? mrb_yield keeps crashing!
+- [#5943](https://github.com/mruby/mruby/issues/5943) TCPSocket#write is failed
+- [#5944](https://github.com/mruby/mruby/issues/5944) Behavior of calling method with a hash variable
+- [#5946](https://github.com/mruby/mruby/pull/5946) Don't switch constant search path from modules to Object
+- [#5949](https://github.com/mruby/mruby/issues/5949) Caller appears to report wrong line when block passed and brackets omitted
+- [0906cd7](https://github.com/mruby/mruby/commit/0906cd7) numeric.c: fix rounding function issues with big numbers
+- [#5974](https://github.com/mruby/mruby/issues/5974) Invalid escape sequences in gem_init.c on windows
+- [#5975](https://github.com/mruby/mruby/issues/5975) Equals comparison fails on extreme ends of 64-bit integers
+- [#5985](https://github.com/mruby/mruby/issues/5985) Sign extension with OP_LOADI32 in get_int_operand()
+- [#5986](https://github.com/mruby/mruby/issues/5986) Fix bugs in String#bytesplice
+- [#5987](https://github.com/mruby/mruby/issues/5987) ~(-1 << 64) is incorrect
+- [#5991](https://github.com/mruby/mruby/issues/5991) 'gets' method not working in mruby-3.2.0
+- [#5994](https://github.com/mruby/mruby/pull/5994) fix typo in mrbgems/mruby-io/src/io.c
+- [#5995](https://github.com/mruby/mruby/issues/5995) One seemingly unnecessary parameter is passed in the block parameters
+- [#6008](https://github.com/mruby/mruby/pull/6008) Make "bintest" independent of directory
+- [b47c8b7](https://github.com/mruby/mruby/commit/b47c8b7) gc.c (clear_all_old): fix a generational GC bug
+- [#6029](https://github.com/mruby/mruby/issues/6029) mruby build fails under mrbgems directory
+- [a264965](https://github.com/mruby/mruby/commit/a264965) mruby-os-memsize/memsize.c: fix irep size calculation
+- [3310e10](https://github.com/mruby/mruby/commit/3310e10) mruby-test/mrbgem.rake: fix mrb_state handling bug
+- [#6041](https://github.com/mruby/mruby/issues/6041) GC Performance may have degraded
+- [#6044](https://github.com/mruby/mruby/issues/6044) Generated presym/table.h contains invalid characters
+- [#6051](https://github.com/mruby/mruby/issues/6051) Null pointer dereference in mrb_addrinfo_unix_path
+- [#6052](https://github.com/mruby/mruby/issues/6052) Null pointer dereference while handling the Proc class
+- [#6055](https://github.com/mruby/mruby/pull/6055) Fix libmruby name for VisualC++
+- [#6060](https://github.com/mruby/mruby/issues/6060) SEGFAULT Issue Related to Fiber Usage in ngx_mruby Development
+- [#6061](https://github.com/mruby/mruby/issues/6061) Performance issue in String#codepoints
+- [#6064](https://github.com/mruby/mruby/issues/6064) MRUBY_PACKAGE_DIR does not always have a value.
+- [#6065](https://github.com/mruby/mruby/issues/6065) Null pointer dereference while handling the Proc class
+- [#6066](https://github.com/mruby/mruby/issues/6066) Null pointer dereference involving Struct.new()
+- [#6067](https://github.com/mruby/mruby/issues/6067) Null pointer dereference in mrb_string_value_cstr
+- [#6068](https://github.com/mruby/mruby/issues/6068) Stack overflow in mrb_vm_exec
+- [#6076](https://github.com/mruby/mruby/pull/6076) Fixed unwinding block that could point to invalid PC
+- [#6084](https://github.com/mruby/mruby/issues/6084) Incorrect symbolic sinks in binary built on Linux
+- [#6087](https://github.com/mruby/mruby/issues/6087) 'Remote branch HEAD not found in upstream origin' error on build
+- [#6089](https://github.com/mruby/mruby/issues/6089) binding.eval() handles def expressions differently from CRuby
+- [#6098](https://github.com/mruby/mruby/issues/6098) Fails to call superclass of wrapped method
+- [#6099](https://github.com/mruby/mruby/issues/6099) `ensure` section is not executed if the function exits via a return in a proc
+- [#6108](https://github.com/mruby/mruby/issues/6108) VM crashes with break
+- [#6118](https://github.com/mruby/mruby/pull/6118) Fixed IO#read with buf
+- [#6120](https://github.com/mruby/mruby/pull/6120) Set EBADF if check_file_descriptor() fails
+- [#6126](https://github.com/mruby/mruby/pull/6126) Fixed return value of `OP_RETURN_BLK` called directly under C function
+- [#6134](https://github.com/mruby/mruby/issues/6134) String#unpack1 returns an array instead of a single string
+- [#6136](https://github.com/mruby/mruby/pull/6136) Fixed when combined `mrb_fiber_resume()` and `Fiber#transfer`
+
+# Pull Requests (User Visible Ones)
+
+- [#5517](https://github.com/mruby/mruby/pull/5517) Fixed local variables not separated between copied binding objects
+- [#5902](https://github.com/mruby/mruby/pull/5902) Replace `MRB_NO_DIRECT_THREADING` with `MRB_USE_VM_SWITCH_DISPATCH`
+- [#5923](https://github.com/mruby/mruby/pull/5923) Demotion `mrb_f_raise()` from `MRB_API`
+- [#5928](https://github.com/mruby/mruby/pull/5928) Improved `rake install`
+- [#5945](https://github.com/mruby/mruby/pull/5945) Avoid exposure for `REnv` objects
+- [#5946](https://github.com/mruby/mruby/pull/5946) Don't switch constant search path from modules to Object
+- [#5966](https://github.com/mruby/mruby/pull/5966) Update default.gembox add mruby debugger mrdb
+- [#5979](https://github.com/mruby/mruby/pull/5979) Allow Class#allocate to be prohibited
+- [#5981](https://github.com/mruby/mruby/pull/5981) `Kernel#binding` responds only to calls from Ruby
+- [#5989](https://github.com/mruby/mruby/pull/5989) Integrate mruby-binding-eval into mruby-eval
+- [#5961](https://github.com/mruby/mruby/pull/5961) Add Docker to build and run all mruby tests. Run pre-commit and generate YARD docs with Docker
+- [#5994](https://github.com/mruby/mruby/pull/5994) fix typo in mrbgems/mruby-io/src/io.c
+- [#6008](https://github.com/mruby/mruby/pull/6008) Make "bintest" independent of directory
+- [#6009](https://github.com/mruby/mruby/pull/6009) Avoid adding /bintest which does not exist
+- [#6011](https://github.com/mruby/mruby/pull/6011) Encode and decode escape characters for presym
+- [#6012](https://github.com/mruby/mruby/pull/6012) Allow tests to be disabled for specific gems; warn about disabled tests
+- [#6013](https://github.com/mruby/mruby/pull/6013) Fix Android toolchain
+- [#6022](https://github.com/mruby/mruby/pull/6022) Build configuration for MS-DOS and DJGPP
+- [#6032](https://github.com/mruby/mruby/pull/6032) Rake: update task clean to remove bin and build folders
+- [#6045](https://github.com/mruby/mruby/pull/6045) Fixes escape sequence bug and enhancements in Presym scanning
+- [#6054](https://github.com/mruby/mruby/pull/6054) Extends `bin/mruby-config`
+- [#6055](https://github.com/mruby/mruby/pull/6055) Fix libmruby name for VisualC++
+- [#6070](https://github.com/mruby/mruby/pull/6070) Demotion mrb_f_raise() in kernel.c from MRB_API too
+- [#6076](https://github.com/mruby/mruby/pull/6076) Fixed unwinding block that could point to invalid PC
+- [#6081](https://github.com/mruby/mruby/pull/6081) Add "x" mode option for IO.open
+- [#6086](https://github.com/mruby/mruby/pull/6086) Add build config for Nintendo Wii
+- [#6097](https://github.com/mruby/mruby/pull/6097) Add a new mrb_fiber_new() with MRB_API
+- [#6103](https://github.com/mruby/mruby/pull/6103) RBreak remembers the CI location
+- [#6105](https://github.com/mruby/mruby/pull/6105) Implement `Fiber#to_s` method
+- [#6106](https://github.com/mruby/mruby/pull/6106) Ease fiber limitations
+- [#6118](https://github.com/mruby/mruby/pull/6118) Fixed IO#read with buf
+- [#6120](https://github.com/mruby/mruby/pull/6120) Set EBADF if check_file_descriptor() fails
+- [#6122](https://github.com/mruby/mruby/pull/6122) Prohibit `Class#allocate` in a different way
+- [#6123](https://github.com/mruby/mruby/pull/6123) Inherit `MRB_FL_UNDEF_ALLOCATE` in subclasses
+- [#6125](https://github.com/mruby/mruby/pull/6125) Allow `OP_RETURN_BLK` to cross C boundaries
+- [#6126](https://github.com/mruby/mruby/pull/6126) Fixed return value of `OP_RETURN_BLK` called directly under C function
+- [#6130](https://github.com/mruby/mruby/pull/6130) `dreamcast_shelf build config`: complete overhaul
+- [#6136](https://github.com/mruby/mruby/pull/6136) Fixed when combined `mrb_fiber_resume()` and `Fiber#transfer`
diff --git a/mruby/README.md b/mruby/README.md
index ed3d9302..21ee55c6 100644
--- a/mruby/README.md
+++ b/mruby/README.md
@@ -30,12 +30,10 @@ of the Ministry of Economy, Trade and Industry of Japan.
## How to get mruby
-To get mruby, you can download the stable version 3.2.0 from the official mruby
+To get mruby, you can download the stable version 3.3.0 from the official mruby
GitHub repository or clone the trunk of the mruby source tree with the "git
clone" command. You can also install and compile mruby using [ruby-install](https://github.com/postmodern/ruby-install), [ruby-build](https://github.com/rbenv/ruby-build) or [rvm](https://github.com/rvm/rvm).
-The stable version 3.2.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/3.2.0.zip](https://github.com/mruby/mruby/archive/3.2.0.zip)
-
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
The trunk of the mruby source tree can be checked out with the
diff --git a/mruby/SECURITY.md b/mruby/SECURITY.md
index 779b06c3..bd80d2dd 100644
--- a/mruby/SECURITY.md
+++ b/mruby/SECURITY.md
@@ -11,7 +11,7 @@ We consider the following issues as vulnerabilities:
- Remote code execution
- Crash caused by a valid Ruby script
-We *don't* consider the following issues as vulnerabilities:
+We _don't_ consider the following issues as vulnerabilities:
- Runtime C undefined behavior (including integer overflow)
- Crash caused by misused API
diff --git a/mruby/build_config/dreamcast_shelf.rb b/mruby/build_config/dreamcast_shelf.rb
index 53adad2a..0edd9470 100644
--- a/mruby/build_config/dreamcast_shelf.rb
+++ b/mruby/build_config/dreamcast_shelf.rb
@@ -4,31 +4,31 @@
# Requires KallistiOS (KOS)
# http://gamedev.allusion.net/softprj/kos/
#
-# Tested on GNU/Linux, macOS and Windows (through MinGW-w64/MSYS2, Cygwin and DreamSDK).
+# This configuration has been improved to be used as KallistiOS Port (kos-ports)
+# Updated: 2023-12-24
+#
+# Tested on GNU/Linux, macOS and Windows (MinGW-w64/MSYS2, Cygwin, DreamSDK)
# DreamSDK is based on MinGW/MSYS: https://dreamsdk.org/
#
-# Input this command on the directory where mruby is installed:
-# make MRUBY_CONFIG=dreamcast_shelf
+# Install mruby for Sega Dreamcast using the "mruby" kos-port.
#
MRuby::CrossBuild.new("dreamcast") do |conf|
toolchain :gcc
- # Support for DreamSDK (based on MinGW/MSYS)
- # To compile mruby with DreamSDK, RubyInstaller for Windows should be installed
- DREAMSDK_HOME = ENV["DREAMSDK_HOME"]
- MSYS_ROOT = !(DREAMSDK_HOME.nil? || DREAMSDK_HOME.empty?) ? "#{DREAMSDK_HOME}/msys/1.0" : ""
+ # Getting critical environment variables
+ KOS_BASE = ENV["KOS_BASE"]
+ KOS_CC_BASE = ENV["KOS_CC_BASE"]
- # Setting paths
- DREAMCAST_PATH = "#{MSYS_ROOT}/opt/toolchains/dc"
- KOS_PATH = "#{DREAMCAST_PATH}/kos"
- BIN_PATH = "#{DREAMCAST_PATH}/sh-elf/bin"
+ if (KOS_BASE.nil? || KOS_BASE.empty? || KOS_CC_BASE.nil? || KOS_CC_BASE.empty?)
+ raise "Error: KallistiOS is required; KOS_BASE/KOS_CC_BASE needs to be declared; Stop."
+ end
# C compiler
- # Flags were extracted from KallistiOS environment files
+ # All flags and settings below were extracted from KallistiOS environment files
conf.cc do |cc|
- cc.command = "#{BIN_PATH}/sh-elf-gcc"
- cc.include_paths << ["#{KOS_PATH}/include", "#{KOS_PATH}/kernel/arch/dreamcast/include", "#{KOS_PATH}/addons/include", "#{KOS_PATH}/../kos-ports/include"]
- cc.flags << ["-O2", "-fomit-frame-pointer", "-ml", "-m4-single-only", "-ffunction-sections", "-fdata-sections", "-Wall", "-g", "-fno-builtin", "-ml", "-m4-single-only", "-Wl,-Ttext=0x8c010000", "-Wl,--gc-sections", "-T#{KOS_PATH}/utils/ldscripts/shlelf.xc", "-nodefaultlibs"]
+ cc.command = "#{KOS_CC_BASE}/bin/sh-elf-gcc"
+ cc.include_paths << ["#{KOS_BASE}/include", "#{KOS_BASE}/kernel/arch/dreamcast/include", "#{KOS_BASE}/addons/include", "#{KOS_BASE}/../kos-ports/include"]
+ cc.flags << ["-O2", "-fomit-frame-pointer", "-fno-builtin", "-ml", "-m4-single-only", "-ffunction-sections", "-fdata-sections", "-matomic-model=soft-imask", "-ftls-model=local-exec", "-Wall", "-g"]
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
cc.defines << %w(_arch_dreamcast)
cc.defines << %w(_arch_sub_pristine)
@@ -39,78 +39,45 @@
cxx.command = conf.cc.command.dup
cxx.include_paths = conf.cc.include_paths.dup
cxx.flags = conf.cc.flags.dup
- cxx.flags << %w(-fno-rtti -fno-exceptions)
+ cxx.flags << %w(-fno-operator-names)
cxx.defines = conf.cc.defines.dup
cxx.compile_options = conf.cc.compile_options.dup
end
# Linker
- # There is an issue when making the mruby library with KallistiOS:
- # 'newlib_kill.o' and 'newlib_getpid.o' aren't found so they are explicitly
- # specified here at least for now.
conf.linker do |linker|
- linker.command="#{BIN_PATH}/sh-elf-gcc"
- linker.flags << ["#{MSYS_ROOT}/opt/toolchains/dc/kos/kernel/build/newlib_kill.o", "#{MSYS_ROOT}/opt/toolchains/dc/kos/kernel/build/newlib_getpid.o", "-Wl,--start-group -lkallisti -lc -lgcc -Wl,--end-group"]
- linker.library_paths << ["#{KOS_PATH}/lib/dreamcast", "#{KOS_PATH}/addons/lib/dreamcast", "#{KOS_PATH}/../kos-ports/lib"]
+ linker.command = "#{KOS_CC_BASE}/bin/sh-elf-gcc"
+ linker.flags << ["-Wl,-Ttext=0x8c010000", "-Wl,--gc-sections", "-T#{KOS_BASE}/utils/ldscripts/shlelf.xc", "-nodefaultlibs", "-Wl,--start-group -lkallisti -lc -lgcc -Wl,--end-group"]
+ linker.library_paths << ["#{KOS_BASE}/lib/dreamcast", "#{KOS_BASE}/addons/lib/dreamcast", "#{KOS_BASE}/../kos-ports/lib"]
end
# Archiver
conf.archiver do |archiver|
- archiver.command = "#{BIN_PATH}/sh-elf-ar"
+ archiver.command = "#{KOS_CC_BASE}/bin/sh-elf-ar"
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
- # No executables
+ # No executables needed for KallistiOS
conf.bins = []
- # Do not build executable test
+ # Do not build test binaries
conf.build_mrbtest_lib_only
- # Disable C++ exception
- conf.disable_cxx_exception
-
- # Gems from core
- # Some Gems are incompatible and were disabled.
+ # Gemboxes
+ conf.gembox "default-no-stdio"
+ conf.gembox "stdlib-ext"
+ conf.gembox "metaprog"
- conf.gem :core => "mruby-array-ext"
+ # Additional Gems
+ # Currently unsupported on KallistiOS: "mruby-io", "mruby-dir", "mruby-socket"
+ conf.gem :core => "mruby-binding"
conf.gem :core => "mruby-catch"
- conf.gem :core => "mruby-class-ext"
- conf.gem :core => "mruby-cmath"
- conf.gem :core => "mruby-compar-ext"
- conf.gem :core => "mruby-compiler"
- conf.gem :core => "mruby-complex"
conf.gem :core => "mruby-enum-chain"
- conf.gem :core => "mruby-enum-ext"
- conf.gem :core => "mruby-enum-lazy"
- conf.gem :core => "mruby-enumerator"
+ conf.gem :core => "mruby-errno"
conf.gem :core => "mruby-error"
- conf.gem :core => "mruby-eval"
conf.gem :core => "mruby-exit"
- conf.gem :core => "mruby-fiber"
- conf.gem :core => "mruby-hash-ext"
-# conf.gem :core => "mruby-io"
- conf.gem :core => "mruby-kernel-ext"
- conf.gem :core => "mruby-math"
- conf.gem :core => "mruby-metaprog"
- conf.gem :core => "mruby-method"
- conf.gem :core => "mruby-numeric-ext"
- conf.gem :core => "mruby-object-ext"
- conf.gem :core => "mruby-objectspace"
conf.gem :core => "mruby-os-memsize"
- conf.gem :core => "mruby-pack"
conf.gem :core => "mruby-print"
conf.gem :core => "mruby-proc-binding"
- conf.gem :core => "mruby-proc-ext"
- conf.gem :core => "mruby-random"
- conf.gem :core => "mruby-range-ext"
- conf.gem :core => "mruby-rational"
conf.gem :core => "mruby-sleep"
-# conf.gem :core => "mruby-socket"
- conf.gem :core => "mruby-sprintf"
- conf.gem :core => "mruby-string-ext"
- conf.gem :core => "mruby-struct"
- conf.gem :core => "mruby-symbol-ext"
-# conf.gem :core => "mruby-test"
-# conf.gem :core => "mruby-time"
- conf.gem :core => "mruby-toplevel-ext"
end
diff --git a/mruby/doc/guides/compile.md b/mruby/doc/guides/compile.md
index 579a49d7..dab17561 100644
--- a/mruby/doc/guides/compile.md
+++ b/mruby/doc/guides/compile.md
@@ -80,7 +80,7 @@ conf.toolchain :clang
#### Visual Studio 2010, 2012 and 2013
Toolchain configuration for Visual Studio on Windows. If you use the
-[Visual Studio Command Prompt](https://msdn.microsoft.com/en-us/library/ms229859\(v=vs.110\).aspx),
+[Visual Studio Command Prompt](),
you normally do not have to specify this manually, since it gets automatically detected by our build process.
```ruby
@@ -460,7 +460,7 @@ compile for `i386` a directory called `i386` is created under the
build directory.
The cross compilation workflow starts in the same way as the normal
-compilation by compiling all *native* libraries and binaries, except
+compilation by compiling all _native_ libraries and binaries, except
for we don't have `host/mrbc` directory (`host` directory itself works
as placeholder for `mrbc`). Afterwards the cross compilation process
proceeds like this:
diff --git a/mruby/doc/guides/debugger.md b/mruby/doc/guides/debugger.md
index 60be1cc8..4e52b7b8 100644
--- a/mruby/doc/guides/debugger.md
+++ b/mruby/doc/guides/debugger.md
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
```bash
$ mrdb --version
-mruby 3.2.0 (2023-02-24)
+mruby 3.3.0 (2024-02-14)
```
## 2.2 Basic Operation
@@ -62,7 +62,7 @@ $ mrdb sample.rb
You can execute the shell commands listed below:
| command | description |
-|:----------------:|:--------------------------------------------------------------------------|
+| :--------------: | :------------------------------------------------------------------------ |
| run | execute programs |
| step | execute stepping |
| continue | execute continuing program |
@@ -83,7 +83,7 @@ You can debug the mruby binary files.
#### 2.2.2.1 Debugging the binary files
- notice
-To debug mruby binary files, you need to compile mruby files with option `-g`.
+ To debug mruby binary files, you need to compile mruby files with option `-g`.
```bash
$ mrbc -g sample.rb
diff --git a/mruby/doc/guides/gc-arena-howto.md b/mruby/doc/guides/gc-arena-howto.md
index 31bee93f..2ac2bdfd 100644
--- a/mruby/doc/guides/gc-arena-howto.md
+++ b/mruby/doc/guides/gc-arena-howto.md
@@ -4,7 +4,7 @@ _This is an English translation of [Matz's blog post][matz blog post]
written in Japanese._
_Some parts are updated to reflect recent changes._
-[matz blog post]:
+[matz blog post]: https://www.rubyist.net/~matz/20130731.html
When you are extending mruby using C language, you may encounter
mysterious "arena overflow error" or memory leak or very slow
diff --git a/mruby/doc/guides/link.md b/mruby/doc/guides/link.md
index 491efc41..ac19aa23 100644
--- a/mruby/doc/guides/link.md
+++ b/mruby/doc/guides/link.md
@@ -51,8 +51,8 @@ for example:
To retrieve compiler options used to build `mruby`, you can use `mruby-config`
command with following options:
-- `--cc` compiler name
-- `--cflags` options passed to compiler
+- `--cc` compiler name
+- `--cflags` options passed to compiler
```console
$ mruby-config --cflags
@@ -66,10 +66,10 @@ compatible to mruby configuration.
To retrieve linker options, you can use `mruby-config` with following options:
-- `--ld` linker name
-- `--ldflags` options passed to linker
-- `--ldflags-before-libs` options passed to linker before linked libraries
-- `--libs` linked libraries
+- `--ld` linker name
+- `--ldflags` options passed to linker
+- `--ldflags-before-libs` options passed to linker before linked libraries
+- `--libs` linked libraries
```console
$ mruby-config --ldflags
diff --git a/mruby/doc/guides/memory.md b/mruby/doc/guides/memory.md
new file mode 100644
index 00000000..8f78ffbe
--- /dev/null
+++ b/mruby/doc/guides/memory.md
@@ -0,0 +1,21 @@
+# Memory Allocation
+
+There are three methods to customize memory allocation in mruby.
+
+1. Provide your own `realloc()`/`free()`
+2. Redefine `mrb_default_allocf()`
+3. Specify a function with `mrb_open_allocf()`
+
+## Provide your own `realloc()`/`free()`
+
+On some platforms, especially on microcontrollers, the standard library may not provide `malloc()`, `realloc()`, and `free()`. In such cases, it may be necessary to define memory allocation functions for the specific platform. mruby uses `realloc()` and `free()` from the standard C library for memory management. By defining these two functions of your own, you can make mruby work. However, note the following two points:
+
+First, `realloc(NULL, size)` behaves the same as malloc(size). Second, `free(NULL)` exits without doing anything.
+
+## Redefine `mrb_default_allocf()`
+
+The only function in mruby that uses the standard C library's memory allocation functions is `mrb_default_allocf()`, defined in `alloc.c`. By defining this function within your application, you can customize the memory management of your application.
+
+## Specify a function with `mrb_open_allocf()`
+
+If you want to perform different memory management for each `mrb_state` within your application, you can use the `mrb_open_allocf()` function to create the `mrb_state` structure. This allows you to specify a memory allocation function (which is compatible with `mrb_default_allocf`) for each `mrb_state`. Although this scheme is not recommended. It may become obsolete in the future, since I have never seen per mrb_state memory management use-case.
diff --git a/mruby/doc/guides/mrbconf.md b/mruby/doc/guides/mrbconf.md
index dc153850..823a0ba1 100644
--- a/mruby/doc/guides/mrbconf.md
+++ b/mruby/doc/guides/mrbconf.md
@@ -25,7 +25,7 @@ MRuby::Build.new do |conf|
end
```
-***NOTE***
+**_NOTE_**
- Use common definitions (`conf.defines`) instead of per-compiler definitions (e.g., `conf.cc.defines`) unless there is a special reason not to.
- It is now deprecated to edit the `include/mruby/mrbconf.h` file or give it directly as a compiler flag, as was the case before.
@@ -123,7 +123,7 @@ end
- Defines value is `1024`.
- Specifies number of `RBasic` per each heap page.
-- To calculate the number of bytes per heap page, it is "(size of management data per heap page) + (size per object) * `MRB_HEAP_PAGE_SIZE`".
+- To calculate the number of bytes per heap page, it is "(size of management data per heap page) + (size per object) \* `MRB_HEAP_PAGE_SIZE`".
In mruby 3.1.0, the "size of management data per heap page" is 6 words, also "size per object" is 6 words.
For a 32-bit CPU, `(6 * 4) + (6 * 4) * MRB_HEAP_PAGE_SIZE` gives the bytes of size per heap page.
Conversely, for example, to keep the size per heap page to 4 Ki bytes,
@@ -135,7 +135,7 @@ end
- Default value is `4`.
- If you're allocating data types that requires alignment more than default value define the
-largest value of required alignment.
+ largest value of required alignment.
`POOL_PAGE_SIZE`
@@ -149,7 +149,7 @@ largest value of required alignment.
- If defined enables fixed size `mrb_state` atexit stack.
- Raises `RuntimeError` when `mrb_state_atexit` call count to same `mrb_state` exceeds
-`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`'s value.
+ `MRB_FIXED_STATE_ATEXIT_STACK_SIZE`'s value.
`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`
diff --git a/mruby/doc/guides/mrbgems.md b/mruby/doc/guides/mrbgems.md
index 999629d4..fe086c1e 100644
--- a/mruby/doc/guides/mrbgems.md
+++ b/mruby/doc/guides/mrbgems.md
@@ -248,7 +248,7 @@ Version requirement supports following operators:
- '<=': is equal or lesser
- '~>': is equal or greater and is lesser than the next major version
- example 1: '~> 2.2.2' means '>= 2.2.2' and '< 2.3.0'
- - example 2: '~> 2.2' means '>= 2.2.0' and '< 3.0.0'
+ - example 2: '~> 2.2' means '>= 2.2.0' and '< 3.0.0'
When more than one version requirements is passed, the dependency must satisfy all of it.
@@ -395,8 +395,8 @@ override existing classes or add new ones in this way. Put all Ruby files
into the `mrblib` directory and all C files into the `src` directory.
mruby codes under `mrblib` directory would be executed after gem init C
-function is called. Make sure *mruby script* depends on *C code* and
-*C code* doesn't depend on *mruby script*.
+function is called. Make sure _mruby script_ depends on _C code_ and
+_C code_ doesn't depend on _mruby script_.
### Pre-Conditions
diff --git a/mruby/doc/guides/symbol.md b/mruby/doc/guides/symbol.md
index c76420da..bae789b6 100644
--- a/mruby/doc/guides/symbol.md
+++ b/mruby/doc/guides/symbol.md
@@ -57,13 +57,13 @@ To save RAM, `mruby` can use compile-time allocation of some symbols. You can
use following macros to get preallocated symbols by including `mruby/presym.h`
header.
-- `MRB_SYM(xor)` //=> xor (Word characters)
-- `MRB_SYM_B(xor)` //=> xor! (Method with Bang)
-- `MRB_SYM_Q(xor)` //=> xor? (Method with Question mark)
-- `MRB_SYM_E(xor)` //=> xor= (Method with Equal)
-- `MRB_CVSYM(xor)` //=> @@xor (Class Variable)
-- `MRB_IVSYM(xor)` //=> @xor (Instance Variable)
-- `MRB_OPSYM(xor)` //=> ^ (Operator)
+- `MRB_SYM(xor)` //=> xor (Word characters)
+- `MRB_SYM_B(xor)` //=> xor! (Method with Bang)
+- `MRB_SYM_Q(xor)` //=> xor? (Method with Question mark)
+- `MRB_SYM_E(xor)` //=> xor= (Method with Equal)
+- `MRB_CVSYM(xor)` //=> @@xor (Class Variable)
+- `MRB_IVSYM(xor)` //=> @xor (Instance Variable)
+- `MRB_OPSYM(xor)` //=> ^ (Operator)
For `MRB_OPSYM()`, specify the names corresponding to operators (see
`MRuby::Presym::OPERATORS` in `lib/mruby/presym.rb` for the names that
diff --git a/mruby/doc/internal/boxing.md b/mruby/doc/internal/boxing.md
index f3bd086e..0cae591e 100644
--- a/mruby/doc/internal/boxing.md
+++ b/mruby/doc/internal/boxing.md
@@ -15,7 +15,7 @@ Some values (called immediate values, e.g. integers, booleans, symbols, etc.) ar
The Word boxing packing bit patterns are like following:
| Types | Bit Pattern |
-|--------|---------------------------------------|
+| ------ | ------------------------------------- |
| object | `xxxxxxxx xxxxxxxx xxxxxxxx xxxxx000` |
| fixnum | `xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxx1` |
| nil | `00000000 00000000 00000000 00000000` |
@@ -24,17 +24,17 @@ The Word boxing packing bit patterns are like following:
| undef | `00000000 00000000 00000000 00010100` |
| symbol | `xxxxxxxx xxxxxxxx xxxxxxxx xxxxxx10` |
-On 64 bit platform (unless `MRB_WORDBOX_NO_FLOAT_TRUNCATE`), float values are also packed in the `mrb_value`. In that case, we drop least significant 2 bits from mantissa.
+On 64-bit platforms (unless `MRB_WORDBOX_NO_FLOAT_TRUNCATE`), float values are also packed in the `mrb_value`. In that case, we drop least significant 2 bits from mantissa.
If you need full precision for floating-point numbers, define `MRB_WORDBOX_NO_FLOAT_TRUNCATE`.
## NaN Boxing
-NaN boxing packs the Ruby data in a floating-point numbers, which represent NaN (Not a Number) values. Under IEEE753 definitions every value that exponent is all set are considered as NaN. That means NaN can represent `2^51` values. NaN boxing is a teaching to pack the values in those NaN representation. In theory, 64 bits pointers are too big to fit in NaN, but practically most OS uses only 48 bits at most for pointers (except for some OS e.g. Solaris).
+NaN boxing packs the Ruby data in a floating-point numbers, which represent NaN (Not a Number) values. Under IEEE753 definitions every value that exponent is all set are considered as NaN. That means NaN can represent `2^51` values. NaN boxing is a teaching to pack the values in those NaN representation. In theory, 64 bit pointers are too big to fit in NaN, but practically most OS use only 48 bits at most for pointers (except for some OS e.g. Solaris).
The NaN boxing packing bit patterns are like following:
| Types | Bit Pattern |
-|--------|---------------------------------------------------------------------------|
+| ------ | ------------------------------------------------------------------------- |
| float | `SEEEEEEE EEEEFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF` |
| +/-inf | `S1111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000` |
| nan | `01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000` |
diff --git a/mruby/doc/mruby3.0.md b/mruby/doc/mruby3.0.md
index 3f7418c4..9d211abb 100644
--- a/mruby/doc/mruby3.0.md
+++ b/mruby/doc/mruby3.0.md
@@ -42,10 +42,10 @@ We have ported some new syntax from CRuby.
## Renamed for consistency
Some configuration macro names are changed for consistency (use `MRB_USE_XXX`
- or `MRB_NO_XXX`).
+or `MRB_NO_XXX`).
-| mruby2 | mruby3 |
-|--------------------------------|---------------------------|
+| mruby2 | mruby3 |
+| ------------------------------ | ------------------------- |
| `MRB_ENABLE_ALL_SYMBOLS` | `MRB_USE_ALL_SYMBOLS` |
| `MRB_ENABLE_CXX_ABI` | `MRB_USE_CXX_ABI` |
| `MRB_ENABLE_CXX_EXCEPTION` | `MRB_USE_CXX_EXCEPTION` |
@@ -149,7 +149,8 @@ No more operand extension
## Changed Instructions
-Jump addresses used to be specified by absolute offset from the start of `iseq`. Now they are relative offset from the address of the next instruction.
+Jump addresses used to be specified by absolute offset from the start of `iseq`. Now they are relative offset from the
+address of the next instruction.
## `Random` now use `xoshiro128++`.
diff --git a/mruby/doc/mruby3.1.md b/mruby/doc/mruby3.1.md
index 188cc836..3450a11e 100644
--- a/mruby/doc/mruby3.1.md
+++ b/mruby/doc/mruby3.1.md
@@ -141,8 +141,8 @@ Method calling instructions are unified. Now `OP_SEND` and `OP_SENDB` (method ca
The brief description of the instructions:
-|`OP_SEND` | BBB | `R[a] = R[a].call(Syms[b],R[a+1..n],R[a+n+1],R[a+n+2]..nk) c=n|nk<<4` |
-|`OP_SENDB` | BBB | `R[a] = R[a].call(Syms[b],R[a+1..n],R[a+n+1..nk],R[a+n+2..nk],&R[a+n+2*nk+2]) c=n|nk<<4` |
+|`OP_SEND` | BBB | `R[a] = R[a].call(Syms[b],R[a+1..n],R[a+n+1],R[a+n+2]..nk) c=n|nk<<4` |
+|`OP_SENDB` | BBB | `R[a] = R[a].call(Syms[b],R[a+1..n],R[a+n+1..nk],R[a+n+2..nk],&R[a+n+2*nk+2]) c=n|nk<<4` |
Operand C specifies the number of arguments. Lower 4 bits (`n`) represents the number of ordinal arguments, and higher 4 bits (`nk`) represents the number of keyword arguments.
When `n == 15`, the method takes arguments packed in an array. When `nk == 15`, the method takes keyword arguments are packed in a hash.
@@ -225,31 +225,31 @@ For better and faster hash values.
Following CVEs are fixed in this release.
-- [CVE-2021-4110](https://nvd.nist.gov/vuln/detail/CVE-2021-4110)
-- [CVE-2021-4188](https://nvd.nist.gov/vuln/detail/CVE-2021-4188)
-- [CVE-2022-0080](https://nvd.nist.gov/vuln/detail/CVE-2022-0080)
-- [CVE-2022-0240](https://nvd.nist.gov/vuln/detail/CVE-2022-0240)
-- [CVE-2022-0326](https://nvd.nist.gov/vuln/detail/CVE-2022-0326)
-- [CVE-2022-0481](https://nvd.nist.gov/vuln/detail/CVE-2022-0481)
-- [CVE-2022-0631](https://nvd.nist.gov/vuln/detail/CVE-2022-0631)
-- [CVE-2022-0632](https://nvd.nist.gov/vuln/detail/CVE-2022-0632)
-- [CVE-2022-0890](https://nvd.nist.gov/vuln/detail/CVE-2022-0890)
-- [CVE-2022-1071](https://nvd.nist.gov/vuln/detail/CVE-2022-1071)
-- [CVE-2022-1106](https://nvd.nist.gov/vuln/detail/CVE-2022-1106)
-- [CVE-2022-1201](https://nvd.nist.gov/vuln/detail/CVE-2022-1201)
-- [CVE-2022-1427](https://nvd.nist.gov/vuln/detail/CVE-2022-1427)
+- [CVE-2021-4110](https://www.cve.org/CVERecord?id=CVE-2021-4110)
+- [CVE-2021-4188](https://www.cve.org/CVERecord?id=CVE-2021-4188)
+- [CVE-2022-0080](https://www.cve.org/CVERecord?id=CVE-2022-0080)
+- [CVE-2022-0240](https://www.cve.org/CVERecord?id=CVE-2022-0240)
+- [CVE-2022-0326](https://www.cve.org/CVERecord?id=CVE-2022-0326)
+- [CVE-2022-0481](https://www.cve.org/CVERecord?id=CVE-2022-0481)
+- [CVE-2022-0631](https://www.cve.org/CVERecord?id=CVE-2022-0631)
+- [CVE-2022-0632](https://www.cve.org/CVERecord?id=CVE-2022-0632)
+- [CVE-2022-0890](https://www.cve.org/CVERecord?id=CVE-2022-0890)
+- [CVE-2022-1071](https://www.cve.org/CVERecord?id=CVE-2022-1071)
+- [CVE-2022-1106](https://www.cve.org/CVERecord?id=CVE-2022-1106)
+- [CVE-2022-1201](https://www.cve.org/CVERecord?id=CVE-2022-1201)
+- [CVE-2022-1427](https://www.cve.org/CVERecord?id=CVE-2022-1427)
## Unaffected CVEs
Following CVEs do not cause problems in this release. They are fixed in the later release.
-- [CVE-2022-0481](https://nvd.nist.gov/vuln/detail/CVE-2022-0481)
-- [CVE-2022-0525](https://nvd.nist.gov/vuln/detail/CVE-2022-0525)
-- [CVE-2022-0570](https://nvd.nist.gov/vuln/detail/CVE-2022-0570)
-- [CVE-2022-0614](https://nvd.nist.gov/vuln/detail/CVE-2022-0614)
-- [CVE-2022-0623](https://nvd.nist.gov/vuln/detail/CVE-2022-0623)
-- [CVE-2022-0630](https://nvd.nist.gov/vuln/detail/CVE-2022-0630)
-- [CVE-2022-0717](https://nvd.nist.gov/vuln/detail/CVE-2022-0817)
-- [CVE-2022-1212](https://nvd.nist.gov/vuln/detail/CVE-2022-1212)
-- [CVE-2022-1276](https://nvd.nist.gov/vuln/detail/CVE-2022-1276)
-- [CVE-2022-1286](https://nvd.nist.gov/vuln/detail/CVE-2022-1286)
+- [CVE-2022-0481](https://www.cve.org/CVERecord?id=CVE-2022-0481)
+- [CVE-2022-0525](https://www.cve.org/CVERecord?id=CVE-2022-0525)
+- [CVE-2022-0570](https://www.cve.org/CVERecord?id=CVE-2022-0570)
+- [CVE-2022-0614](https://www.cve.org/CVERecord?id=CVE-2022-0614)
+- [CVE-2022-0623](https://www.cve.org/CVERecord?id=CVE-2022-0623)
+- [CVE-2022-0630](https://www.cve.org/CVERecord?id=CVE-2022-0630)
+- [CVE-2022-0717](https://www.cve.org/CVERecord?id=CVE-2022-0817)
+- [CVE-2022-1212](https://www.cve.org/CVERecord?id=CVE-2022-1212)
+- [CVE-2022-1276](https://www.cve.org/CVERecord?id=CVE-2022-1276)
+- [CVE-2022-1286](https://www.cve.org/CVERecord?id=CVE-2022-1286)
diff --git a/mruby/doc/mruby3.2.md b/mruby/doc/mruby3.2.md
index 59bd1e2e..587a0e6d 100644
--- a/mruby/doc/mruby3.2.md
+++ b/mruby/doc/mruby3.2.md
@@ -59,21 +59,21 @@ Intentional reliance on previous behavior may cause compatibility problems in yo
Following CVEs are fixed.
-- [CVE-2022-0080](https://nvd.nist.gov/vuln/detail/CVE-2022-0080)
-- [CVE-2022-0240](https://nvd.nist.gov/vuln/detail/CVE-2022-0240)
-- [CVE-2022-0326](https://nvd.nist.gov/vuln/detail/CVE-2022-0326)
-- [CVE-2022-0481](https://nvd.nist.gov/vuln/detail/CVE-2022-0481)
-- [CVE-2022-0525](https://nvd.nist.gov/vuln/detail/CVE-2022-0525)
-- [CVE-2022-0570](https://nvd.nist.gov/vuln/detail/CVE-2022-0570)
-- [CVE-2022-0614](https://nvd.nist.gov/vuln/detail/CVE-2022-0614)
-- [CVE-2022-0623](https://nvd.nist.gov/vuln/detail/CVE-2022-0623)
-- [CVE-2022-0630](https://nvd.nist.gov/vuln/detail/CVE-2022-0630)
-- [CVE-2022-0631](https://nvd.nist.gov/vuln/detail/CVE-2022-0631)
-- [CVE-2022-0632](https://nvd.nist.gov/vuln/detail/CVE-2022-0632)
-- [CVE-2022-0717](https://nvd.nist.gov/vuln/detail/CVE-2022-0717)
-- [CVE-2022-0890](https://nvd.nist.gov/vuln/detail/CVE-2022-0890)
-- [CVE-2022-1106](https://nvd.nist.gov/vuln/detail/CVE-2022-1106)
-- [CVE-2022-1212](https://nvd.nist.gov/vuln/detail/CVE-2022-1212)
-- [CVE-2022-1276](https://nvd.nist.gov/vuln/detail/CVE-2022-1276)
-- [CVE-2022-1286](https://nvd.nist.gov/vuln/detail/CVE-2022-1286)
-- [CVE-2022-1934](https://nvd.nist.gov/vuln/detail/CVE-2022-1934)
+- [CVE-2022-0080](https://www.cve.org/CVERecord?id=CVE-2022-0080)
+- [CVE-2022-0240](https://www.cve.org/CVERecord?id=CVE-2022-0240)
+- [CVE-2022-0326](https://www.cve.org/CVERecord?id=CVE-2022-0326)
+- [CVE-2022-0481](https://www.cve.org/CVERecord?id=CVE-2022-0481)
+- [CVE-2022-0525](https://www.cve.org/CVERecord?id=CVE-2022-0525)
+- [CVE-2022-0570](https://www.cve.org/CVERecord?id=CVE-2022-0570)
+- [CVE-2022-0614](https://www.cve.org/CVERecord?id=CVE-2022-0614)
+- [CVE-2022-0623](https://www.cve.org/CVERecord?id=CVE-2022-0623)
+- [CVE-2022-0630](https://www.cve.org/CVERecord?id=CVE-2022-0630)
+- [CVE-2022-0631](https://www.cve.org/CVERecord?id=CVE-2022-0631)
+- [CVE-2022-0632](https://www.cve.org/CVERecord?id=CVE-2022-0632)
+- [CVE-2022-0717](https://www.cve.org/CVERecord?id=CVE-2022-0717)
+- [CVE-2022-0890](https://www.cve.org/CVERecord?id=CVE-2022-0890)
+- [CVE-2022-1106](https://www.cve.org/CVERecord?id=CVE-2022-1106)
+- [CVE-2022-1212](https://www.cve.org/CVERecord?id=CVE-2022-1212)
+- [CVE-2022-1276](https://www.cve.org/CVERecord?id=CVE-2022-1276)
+- [CVE-2022-1286](https://www.cve.org/CVERecord?id=CVE-2022-1286)
+- [CVE-2022-1934](https://www.cve.org/CVERecord?id=CVE-2022-1934)
diff --git a/mruby/doc/mruby3.3.md b/mruby/doc/mruby3.3.md
new file mode 100644
index 00000000..eec7732f
--- /dev/null
+++ b/mruby/doc/mruby3.3.md
@@ -0,0 +1,186 @@
+# User visible changes in `mruby3.3` from `mruby3.2`
+
+"**_NOTE_**:" are changes to be aware of.
+
+# The language
+
+- aliases work properly with `super` ([2ad3f0e](https://github.com/mruby/mruby/commit/2ad3f0e))
+- `callee` method work differently with aliases in mruby ([f2dc76e](https://github.com/mruby/mruby/commit/f2dc76e))
+- define `Kernel#respond_to_missing?` method ([347586e](https://github.com/mruby/mruby/commit/347586e))
+- `_inspect` method (`inspect` with recursive check) is removed
+ ([e2bbf75](https://github.com/mruby/mruby/commit/e2bbf75), [5cb0c74](https://github.com/mruby/mruby/commit/5cb0c74), [113565a](https://github.com/mruby/mruby/commit/113565a),
+ [0713f2a](https://github.com/mruby/mruby/commit/0713f2a), [6ae6b63](https://github.com/mruby/mruby/commit/6ae6b63), [fc9fffc](https://github.com/mruby/mruby/commit/fc9fffc))
+- `__printstr__` method is removed; use `print` instead
+ ([acecee0](https://github.com/mruby/mruby/commit/acecee0), [192e6e3](https://github.com/mruby/mruby/commit/192e6e3))
+- New method `String#bytesplice` ([5274647](https://github.com/mruby/mruby/commit/5274647), [a2e2e83](https://github.com/mruby/mruby/commit/a2e2e83))
+- Allow `return` in blocks to cross C boundaries ([#6125](https://github.com/mruby/mruby/pull/6125))
+
+# Configuration
+
+- mruby can be built using Docker now. Try `docker-compose build` for example. ([#5961](https://github.com/mruby/mruby/pull/5961))
+- New Platform: DJGPP (MS-DOS) ([#6022](https://github.com/mruby/mruby/pull/6022))
+- New Platform: Nintendo Wii ([#6086](https://github.com/mruby/mruby/pull/6086))
+- Improved Platform: Android ([#6013](https://github.com/mruby/mruby/pull/6013))
+- Improved Platform: Dreamcast ([#6130](https://github.com/mruby/mruby/pull/6130))
+- Allow tests to be disabled for specific gems; warn about disabled tests ([#6012](https://github.com/mruby/mruby/pull/6012))
+- Replace `MRB_NO_DIRECT_THREADING` with `MRB_USE_VM_SWITCH_DISPATCH` ([#5902](https://github.com/mruby/mruby/pull/5902))
+
+# mruby memory API
+
+- `mrb_default_allocf` can be overridden by the application ([34c5d96](https://github.com/mruby/mruby/commit/34c5d96))
+- `mrb_open_allocf` will be deprecated ([cfee5c2](https://github.com/mruby/mruby/commit/cfee5c2))
+
+# Changes in C API
+
+- add new error handling API functions ([8c8bbd9](https://github.com/mruby/mruby/commit/8c8bbd9))
+- Add `mrb_vm_ci_env_clear()` function with `MRB_API` ([#5945](https://github.com/mruby/mruby/pull/5945))
+- a new function `mrb_check_frozen_value()` ([ccdf75c](https://github.com/mruby/mruby/commit/ccdf75c))
+- avoid formatting in `mrb_bug()` ([82a48bd](https://github.com/mruby/mruby/commit/82a48bd))
+ **_NOTE_**: If you are using it, you must give a simple string or replace it with a call to `mrb_raise()` series.
+- stop using `mrbc_` prefix for compiler context ([c5e3cbe](https://github.com/mruby/mruby/commit/c5e3cbe))
+ The same names are provided as before, but we recommend replacing them.
+- Allow `Class#allocate` to be prohibited
+ ([#5979](https://github.com/mruby/mruby/pull/5979), [#6122](https://github.com/mruby/mruby/pull/6122), [#6123](https://github.com/mruby/mruby/pull/6123))
+ To disable `#allocate`, use `MRB_UNDEF_ALLOCATOR()`.
+ This is also automatically applied when the subclass is created, but to explicitly allow it, use `MRB_DEFINE_ALLOCATOR()`.
+
+# Changes in mrbgems
+
+- **default.gembox**: Add mruby debugger mrdb (`mruby-bin-debugger`) ([#5966](https://github.com/mruby/mruby/pull/5966))
+- **mruby-bin-config**: new options `--cxx`, `--cxxflags`, `--as`, `--asflags`, `--objc`, `--objcflags` ([#6054](https://github.com/mruby/mruby/pull/6054))
+- **mruby-binding**: renamed from `mruby-binding-core` of mruby3.2 ([11af5db](https://github.com/mruby/mruby/commit/11af5db))
+ **_NOTE_**: If using `mruby-binding-core` of mruby 3.2, replace it with `mruby-binding`.
+- **mruby-binding**: implemented `Binding#initialize_copy` method ([#5517](https://github.com/mruby/mruby/pull/5517))
+- **mruby-binding**: `Kernel#binding` responds only to calls from Ruby ([#5981](https://github.com/mruby/mruby/pull/5981))
+- **mruby-compar-ext**: Comparable#clamp to accept nil as arguments ([836bebc](https://github.com/mruby/mruby/commit/836bebc))
+- **mruby-compiler**: add print name for identifier tokens ([d7b2e3a](https://github.com/mruby/mruby/commit/d7b2e3a))
+- **mruby-data**: allow empty Data ([927a9df](https://github.com/mruby/mruby/commit/927a9df))
+- **mruby-enumerator**: remove internal attribute methods `obj`, `args`, `kwd`, `meth`, `fib`. ([735fa24](https://github.com/mruby/mruby/commit/735fa24))
+- **mruby-enumerator**: add Enumerator#size ([861f8bd](https://github.com/mruby/mruby/commit/861f8bd))
+- **mruby-eval**: merged `mruby-binding` of mruby3.2 ([501b22a](https://github.com/mruby/mruby/commit/501b22a), [#5989](https://github.com/mruby/mruby/pull/5989))
+ **_NOTE_**: If using `mruby-binding` of mruby 3.2, replace it with `mruby-eval`.
+- **mruby-fiber**: Add a new `mrb_fiber_new()` with `MRB_API` ([#6097](https://github.com/mruby/mruby/pull/6097))
+- **mruby-fiber**: Allows calling `Fiber#resume` from C ([#6106](https://github.com/mruby/mruby/pull/6106))
+- **mruby-fiber**: `Fiber#to_s` format changed ([#6105](https://github.com/mruby/mruby/pull/6105))
+- **mruby-io**: add File#atime and File#ctime ([321cfe9](https://github.com/mruby/mruby/commit/321cfe9))
+- **mruby-io**: Add "x" mode option for `IO.open` ([#6081](https://github.com/mruby/mruby/pull/6081))
+- **mruby-io**: File.new should not take blocks ([53de964](https://github.com/mruby/mruby/commit/53de964))
+- **mruby-method**: `Method#to_s` format changed ([f5bc82f](https://github.com/mruby/mruby/commit/f5bc82f), [02f189c](https://github.com/mruby/mruby/commit/02f189c))
+- **mruby-numeric-ext**: `int.pow(n,m)` to take bigint as exponential ([d482eab](https://github.com/mruby/mruby/commit/d482eab))
+- **mruby-pack**: support new directives `j`, `J`, `b`, `B`, `#`
+ ([2a1e3a5](https://github.com/mruby/mruby/commit/2a1e3a5), [e7021f1](https://github.com/mruby/mruby/commit/e7021f1), [e17f325](https://github.com/mruby/mruby/commit/e17f325))
+- **mruby-range-ext**: new method `Range#overlap?` ([384d0e2](https://github.com/mruby/mruby/commit/384d0e2))
+- **mruby-string-ext**: Add `String#valid_encoding?` method ([eabe2d9](https://github.com/mruby/mruby/commit/eabe2d9))
+- **mruby-struct**: allow empty Struct when a name is not given ([c212ede](https://github.com/mruby/mruby/commit/c212ede))
+- **mruby-time**: should allow year before 1900 ([e5de08b](https://github.com/mruby/mruby/commit/e5de08b))
+- **mruby-time**: support bigint to time_t if necessary ([7096d27](https://github.com/mruby/mruby/commit/7096d27))
+- **mruby-time**: need to handle negative time_t ([b064d7e](https://github.com/mruby/mruby/commit/b064d7e))
+
+# Changes in build system
+
+- Extended `rake install` task ([#5928](https://github.com/mruby/mruby/pull/5928))
+ **_NOTE_**: Due to this impact, executable files in the `mruby/bin/` directory by default are now symbolic links (batch files on Windows).
+ If previously relied on those executables, should be replaced with direct references to the entity created under the build directory (e.g. `mruby/build/host/bin/`).
+- Encode and decode escape characters for presym ([#6011](https://github.com/mruby/mruby/pull/6011))
+- Rakefile: remove default build target directories in `deep_clean` ([#6032](https://github.com/mruby/mruby/pull/6032), [1e38569](https://github.com/mruby/mruby/commit/1e38569))
+
+# Other breaking changes
+
+- `mrb_f_raise()` is now an internal function
+ ([#5923](https://github.com/mruby/mruby/pull/5923), [#6070](https://github.com/mruby/mruby/pull/6070))
+- `mrb_make_exception()` is now an internal function with different parameters
+ ([431f83e](https://github.com/mruby/mruby/commit/431f83e), [78137f3](https://github.com/mruby/mruby/commit/78137f3))
+- The `File#path` method no longer uses the `#to_path` method for implicit conversion
+ ([d86c4a7](https://github.com/mruby/mruby/commit/d86c4a7))
+- stop mrb isolation for each test file ([a20fbe5](https://github.com/mruby/mruby/commit/a20fbe5))
+- RBreak remembers the CI location ([#6103](https://github.com/mruby/mruby/pull/6103))
+
+# Bugs Fixed
+
+- [#5724](https://github.com/mruby/mruby/issues/5724) Rational#\*\* is missing
+- [#5725](https://github.com/mruby/mruby/issues/5725) weird const_missing exceptions in mrblib code
+- [#5789](https://github.com/mruby/mruby/issues/5789) No memory release of backtrace information due to stack error
+- [#5932](https://github.com/mruby/mruby/issues/5932) How to create a block using the C API? mrb_yield keeps crashing!
+- [#5943](https://github.com/mruby/mruby/issues/5943) TCPSocket#write is failed
+- [#5944](https://github.com/mruby/mruby/issues/5944) Behavior of calling method with a hash variable
+- [#5946](https://github.com/mruby/mruby/pull/5946) Don't switch constant search path from modules to Object
+- [#5949](https://github.com/mruby/mruby/issues/5949) Caller appears to report wrong line when block passed and brackets omitted
+- [0906cd7](https://github.com/mruby/mruby/commit/0906cd7) numeric.c: fix rounding function issues with big numbers
+- [#5974](https://github.com/mruby/mruby/issues/5974) Invalid escape sequences in gem_init.c on windows
+- [#5975](https://github.com/mruby/mruby/issues/5975) Equals comparison fails on extreme ends of 64-bit integers
+- [#5985](https://github.com/mruby/mruby/issues/5985) Sign extension with OP_LOADI32 in get_int_operand()
+- [#5986](https://github.com/mruby/mruby/issues/5986) Fix bugs in String#bytesplice
+- [#5987](https://github.com/mruby/mruby/issues/5987) ~(-1 << 64) is incorrect
+- [#5991](https://github.com/mruby/mruby/issues/5991) 'gets' method not working in mruby-3.2.0
+- [#5994](https://github.com/mruby/mruby/pull/5994) fix typo in mrbgems/mruby-io/src/io.c
+- [#5995](https://github.com/mruby/mruby/issues/5995) One seemingly unnecessary parameter is passed in the block parameters
+- [#6008](https://github.com/mruby/mruby/pull/6008) Make "bintest" independent of directory
+- [b47c8b7](https://github.com/mruby/mruby/commit/b47c8b7) gc.c (clear_all_old): fix a generational GC bug
+- [#6029](https://github.com/mruby/mruby/issues/6029) mruby build fails under mrbgems directory
+- [a264965](https://github.com/mruby/mruby/commit/a264965) mruby-os-memsize/memsize.c: fix irep size calculation
+- [3310e10](https://github.com/mruby/mruby/commit/3310e10) mruby-test/mrbgem.rake: fix mrb_state handling bug
+- [#6041](https://github.com/mruby/mruby/issues/6041) GC Performance may have degraded
+- [#6044](https://github.com/mruby/mruby/issues/6044) Generated presym/table.h contains invalid characters
+- [#6051](https://github.com/mruby/mruby/issues/6051) Null pointer dereference in mrb_addrinfo_unix_path
+- [#6052](https://github.com/mruby/mruby/issues/6052) Null pointer dereference while handling the Proc class
+- [#6055](https://github.com/mruby/mruby/pull/6055) Fix libmruby name for VisualC++
+- [#6060](https://github.com/mruby/mruby/issues/6060) SEGFAULT Issue Related to Fiber Usage in ngx_mruby Development
+- [#6061](https://github.com/mruby/mruby/issues/6061) Performance issue in String#codepoints
+- [#6064](https://github.com/mruby/mruby/issues/6064) MRUBY_PACKAGE_DIR does not always have a value.
+- [#6065](https://github.com/mruby/mruby/issues/6065) Null pointer dereference while handling the Proc class
+- [#6066](https://github.com/mruby/mruby/issues/6066) Null pointer dereference involving Struct.new()
+- [#6067](https://github.com/mruby/mruby/issues/6067) Null pointer dereference in mrb_string_value_cstr
+- [#6068](https://github.com/mruby/mruby/issues/6068) Stack overflow in mrb_vm_exec
+- [#6076](https://github.com/mruby/mruby/pull/6076) Fixed unwinding block that could point to invalid PC
+- [#6084](https://github.com/mruby/mruby/issues/6084) Incorrect symbolic sinks in binary built on Linux
+- [#6087](https://github.com/mruby/mruby/issues/6087) 'Remote branch HEAD not found in upstream origin' error on build
+- [#6089](https://github.com/mruby/mruby/issues/6089) binding.eval() handles def expressions differently from CRuby
+- [#6098](https://github.com/mruby/mruby/issues/6098) Fails to call superclass of wrapped method
+- [#6099](https://github.com/mruby/mruby/issues/6099) `ensure` section is not executed if the function exits via a return in a proc
+- [#6108](https://github.com/mruby/mruby/issues/6108) VM crashes with break
+- [#6118](https://github.com/mruby/mruby/pull/6118) Fixed IO#read with buf
+- [#6120](https://github.com/mruby/mruby/pull/6120) Set EBADF if check_file_descriptor() fails
+- [#6126](https://github.com/mruby/mruby/pull/6126) Fixed return value of `OP_RETURN_BLK` called directly under C function
+- [#6134](https://github.com/mruby/mruby/issues/6134) String#unpack1 returns an array instead of a single string
+- [#6136](https://github.com/mruby/mruby/pull/6136) Fixed when combined `mrb_fiber_resume()` and `Fiber#transfer`
+
+# Pull Requests (User Visible Ones)
+
+- [#5517](https://github.com/mruby/mruby/pull/5517) Fixed local variables not separated between copied binding objects
+- [#5902](https://github.com/mruby/mruby/pull/5902) Replace `MRB_NO_DIRECT_THREADING` with `MRB_USE_VM_SWITCH_DISPATCH`
+- [#5923](https://github.com/mruby/mruby/pull/5923) Demotion `mrb_f_raise()` from `MRB_API`
+- [#5928](https://github.com/mruby/mruby/pull/5928) Improved `rake install`
+- [#5945](https://github.com/mruby/mruby/pull/5945) Avoid exposure for `REnv` objects
+- [#5946](https://github.com/mruby/mruby/pull/5946) Don't switch constant search path from modules to Object
+- [#5966](https://github.com/mruby/mruby/pull/5966) Update default.gembox add mruby debugger mrdb
+- [#5979](https://github.com/mruby/mruby/pull/5979) Allow Class#allocate to be prohibited
+- [#5981](https://github.com/mruby/mruby/pull/5981) `Kernel#binding` responds only to calls from Ruby
+- [#5989](https://github.com/mruby/mruby/pull/5989) Integrate mruby-binding-eval into mruby-eval
+- [#5961](https://github.com/mruby/mruby/pull/5961) Add Docker to build and run all mruby tests. Run pre-commit and generate YARD docs with Docker
+- [#5994](https://github.com/mruby/mruby/pull/5994) fix typo in mrbgems/mruby-io/src/io.c
+- [#6008](https://github.com/mruby/mruby/pull/6008) Make "bintest" independent of directory
+- [#6009](https://github.com/mruby/mruby/pull/6009) Avoid adding /bintest which does not exist
+- [#6011](https://github.com/mruby/mruby/pull/6011) Encode and decode escape characters for presym
+- [#6012](https://github.com/mruby/mruby/pull/6012) Allow tests to be disabled for specific gems; warn about disabled tests
+- [#6013](https://github.com/mruby/mruby/pull/6013) Fix Android toolchain
+- [#6022](https://github.com/mruby/mruby/pull/6022) Build configuration for MS-DOS and DJGPP
+- [#6032](https://github.com/mruby/mruby/pull/6032) Rake: update task clean to remove bin and build folders
+- [#6045](https://github.com/mruby/mruby/pull/6045) Fixes escape sequence bug and enhancements in Presym scanning
+- [#6054](https://github.com/mruby/mruby/pull/6054) Extends `bin/mruby-config`
+- [#6055](https://github.com/mruby/mruby/pull/6055) Fix libmruby name for VisualC++
+- [#6070](https://github.com/mruby/mruby/pull/6070) Demotion mrb_f_raise() in kernel.c from MRB_API too
+- [#6076](https://github.com/mruby/mruby/pull/6076) Fixed unwinding block that could point to invalid PC
+- [#6081](https://github.com/mruby/mruby/pull/6081) Add "x" mode option for IO.open
+- [#6086](https://github.com/mruby/mruby/pull/6086) Add build config for Nintendo Wii
+- [#6097](https://github.com/mruby/mruby/pull/6097) Add a new mrb_fiber_new() with MRB_API
+- [#6103](https://github.com/mruby/mruby/pull/6103) RBreak remembers the CI location
+- [#6105](https://github.com/mruby/mruby/pull/6105) Implement `Fiber#to_s` method
+- [#6106](https://github.com/mruby/mruby/pull/6106) Ease fiber limitations
+- [#6118](https://github.com/mruby/mruby/pull/6118) Fixed IO#read with buf
+- [#6120](https://github.com/mruby/mruby/pull/6120) Set EBADF if check_file_descriptor() fails
+- [#6122](https://github.com/mruby/mruby/pull/6122) Prohibit `Class#allocate` in a different way
+- [#6123](https://github.com/mruby/mruby/pull/6123) Inherit `MRB_FL_UNDEF_ALLOCATE` in subclasses
+- [#6125](https://github.com/mruby/mruby/pull/6125) Allow `OP_RETURN_BLK` to cross C boundaries
+- [#6126](https://github.com/mruby/mruby/pull/6126) Fixed return value of `OP_RETURN_BLK` called directly under C function
+- [#6130](https://github.com/mruby/mruby/pull/6130) `dreamcast_shelf build config`: complete overhaul
+- [#6136](https://github.com/mruby/mruby/pull/6136) Fixed when combined `mrb_fiber_resume()` and `Fiber#transfer`
diff --git a/mruby/docker-compose.yml b/mruby/docker-compose.yml
index 55b61a87..009947b0 100644
--- a/mruby/docker-compose.yml
+++ b/mruby/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '3.8'
+version: "3.8"
services:
test:
build:
diff --git a/mruby/include/mruby.h b/mruby/include/mruby.h
index 3ed86f8c..828bb9d2 100644
--- a/mruby/include/mruby.h
+++ b/mruby/include/mruby.h
@@ -162,11 +162,11 @@ struct mrb_state;
*
* The function pointing it must behave similarly as realloc except:
* - If ptr is NULL it must allocate new space.
- * - If s is NULL, ptr must be freed.
+ * - If size is zero, ptr must be freed.
*
* See @see mrb_default_allocf for the default implementation.
*/
-typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud);
+typedef void* (*mrb_allocf) (struct mrb_state *mrb, void *ptr, size_t size, void *ud);
#ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE
#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5
@@ -798,6 +798,8 @@ MRB_API struct RClass * mrb_module_get_under_id(mrb_state *mrb, struct RClass *o
MRB_API void mrb_notimplement(mrb_state*);
/* a function to be replacement of unimplemented method */
MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value);
+/* just return it self */
+MRB_API mrb_value mrb_obj_itself(mrb_state*, mrb_value);
/**
* Duplicate an object.
diff --git a/mruby/include/mruby/class.h b/mruby/include/mruby/class.h
index a3e1c0d1..5be1b8e9 100644
--- a/mruby/include/mruby/class.h
+++ b/mruby/include/mruby/class.h
@@ -57,7 +57,8 @@ mrb_class(mrb_state *mrb, mrb_value v)
19: is_prepended
18: is_origin
17: is_inherited (used by method cache)
- 6-16: unused
+ 7-16: unused
+ 6: prohibit Class#allocate
0-5: instance type
*/
#define MRB_FL_CLASS_IS_PREPENDED (1 << 19)
@@ -74,6 +75,10 @@ mrb_class(mrb_state *mrb, mrb_value v)
#define MRB_INSTANCE_TT_MASK (0x1F)
#define MRB_SET_INSTANCE_TT(c, tt) ((c)->flags = (((c)->flags & ~MRB_INSTANCE_TT_MASK) | (char)(tt)))
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)((c)->flags & MRB_INSTANCE_TT_MASK)
+#define MRB_FL_UNDEF_ALLOCATE (1 << 6)
+#define MRB_UNDEF_ALLOCATOR(c) (mrb_assert((c)->tt == MRB_TT_CLASS), (c)->flags |= MRB_FL_UNDEF_ALLOCATE)
+#define MRB_UNDEF_ALLOCATOR_P(c) ((c)->flags & MRB_FL_UNDEF_ALLOCATE)
+#define MRB_DEFINE_ALLOCATOR(c) ((c)->flags &= ~MRB_FL_UNDEF_ALLOCATE)
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b);
diff --git a/mruby/include/mruby/error.h b/mruby/include/mruby/error.h
index ee6fe8ff..e8c63dc3 100644
--- a/mruby/include/mruby/error.h
+++ b/mruby/include/mruby/error.h
@@ -17,8 +17,8 @@ MRB_BEGIN_DECL
struct RException {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
- struct RObject *mesg; // NULL or probably RString
- struct RObject *backtrace; // NULL, RArray or RData
+ struct RBasic *mesg; // NULL or probably RString
+ struct RBasic *backtrace; // NULL, RArray or RData
};
/* error that should terminate execution */
diff --git a/mruby/include/mruby/internal.h b/mruby/include/mruby/internal.h
index 37c6fa1f..a2948961 100644
--- a/mruby/include/mruby/internal.h
+++ b/mruby/include/mruby/internal.h
@@ -61,6 +61,18 @@ mrb_value mrb_exc_mesg_get(mrb_state *mrb, struct RException *exc);
mrb_value mrb_f_raise(mrb_state*, mrb_value);
mrb_value mrb_make_exception(mrb_state *mrb, mrb_value exc, mrb_value mesg);
+struct RBacktrace {
+ MRB_OBJECT_HEADER;
+ size_t len;
+ struct mrb_backtrace_location *locations;
+};
+
+struct mrb_backtrace_location {
+ mrb_sym method_id;
+ int32_t idx;
+ const mrb_irep *irep;
+};
+
/* gc */
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
diff --git a/mruby/include/mruby/opcode.h b/mruby/include/mruby/opcode.h
index 24959816..19da77fb 100644
--- a/mruby/include/mruby/opcode.h
+++ b/mruby/include/mruby/opcode.h
@@ -19,10 +19,6 @@ enum mrb_insn {
#define OP_L_LAMBDA (OP_L_STRICT|OP_L_CAPTURE)
#define OP_L_BLOCK OP_L_CAPTURE
-#define OP_R_NORMAL 0
-#define OP_R_BREAK 1
-#define OP_R_RETURN 2
-
#define PEEK_B(pc) (*(pc))
#define PEEK_S(pc) ((pc)[0]<<8|(pc)[1])
#define PEEK_W(pc) ((pc)[0]<<16|(pc)[1]<<8|(pc)[2])
diff --git a/mruby/include/mruby/string.h b/mruby/include/mruby/string.h
index cd300f8b..ac6740c5 100644
--- a/mruby/include/mruby/string.h
+++ b/mruby/include/mruby/string.h
@@ -79,18 +79,19 @@ struct RStringEmbed {
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
#ifdef MRB_UTF8_STRING
-# define RSTR_ASCII_P(s) ((s)->flags & MRB_STR_ASCII)
-# define RSTR_SET_ASCII_FLAG(s) ((s)->flags |= MRB_STR_ASCII)
-# define RSTR_UNSET_ASCII_FLAG(s) ((s)->flags &= ~MRB_STR_ASCII)
-# define RSTR_WRITE_ASCII_FLAG(s, v) (RSTR_UNSET_ASCII_FLAG(s), (s)->flags |= v)
-# define RSTR_COPY_ASCII_FLAG(dst, src) RSTR_WRITE_ASCII_FLAG(dst, RSTR_ASCII_P(src))
+# define RSTR_SINGLE_BYTE_P(s) ((s)->flags & MRB_STR_SINGLE_BYTE)
+# define RSTR_SET_SINGLE_BYTE_FLAG(s) ((s)->flags |= MRB_STR_SINGLE_BYTE)
+# define RSTR_UNSET_SINGLE_BYTE_FLAG(s) ((s)->flags &= ~MRB_STR_SINGLE_BYTE)
+# define RSTR_WRITE_SINGLE_BYTE_FLAG(s, v) (RSTR_UNSET_SINGLE_BYTE_FLAG(s), (s)->flags |= v)
+# define RSTR_COPY_SINGLE_BYTE_FLAG(dst, src) RSTR_WRITE_SINGLE_BYTE_FLAG(dst, RSTR_SINGLE_BYTE_P(src))
#else
-# define RSTR_ASCII_P(s) (void)0
-# define RSTR_SET_ASCII_FLAG(s) (void)0
-# define RSTR_UNSET_ASCII_FLAG(s) (void)0
-# define RSTR_WRITE_ASCII_FLAG(s, v) (void)0
-# define RSTR_COPY_ASCII_FLAG(dst, src) (void)0
+# define RSTR_SINGLE_BYTE_P(s) (void)1
+# define RSTR_SET_SINGLE_BYTE_FLAG(s) (void)0
+# define RSTR_UNSET_SINGLE_BYTE_FLAG(s) (void)0
+# define RSTR_WRITE_SINGLE_BYTE_FLAG(s, v) (void)0
+# define RSTR_COPY_SINGLE_BYTE_FLAG(dst, src) (void)0
#endif
+#define RSTR_SET_ASCII_FLAG(s) RSTR_SET_SINGLE_BYTE_FLAG(s)
/**
* Returns a pointer from a Ruby string
@@ -108,7 +109,7 @@ struct RStringEmbed {
#define MRB_STR_FSHARED 2
#define MRB_STR_NOFREE 4
#define MRB_STR_EMBED 8 /* type flags up to here */
-#define MRB_STR_ASCII 16
+#define MRB_STR_SINGLE_BYTE 16
#define MRB_STR_EMBED_LEN_SHIFT 6
#define MRB_STR_EMBED_LEN_BIT 5
#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BIT) - 1) << MRB_STR_EMBED_LEN_SHIFT)
diff --git a/mruby/include/mruby/value.h b/mruby/include/mruby/value.h
index 71cdaca3..16da2cbd 100644
--- a/mruby/include/mruby/value.h
+++ b/mruby/include/mruby/value.h
@@ -159,7 +159,8 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
f(MRB_TT_BREAK, struct RBreak, "break") \
f(MRB_TT_COMPLEX, struct RComplex, "Complex") \
f(MRB_TT_RATIONAL, struct RRational, "Rational") \
- f(MRB_TT_BIGINT, struct RBigint, "Integer")
+ f(MRB_TT_BIGINT, struct RBigint, "Integer") \
+ f(MRB_TT_BACKTRACE, struct RBacktrace, "backtrace")
enum mrb_vtype {
#define MRB_VTYPE_DEFINE(tt, type, name) tt,
diff --git a/mruby/include/mruby/version.h b/mruby/include/mruby/version.h
index c2fc83d8..2562603c 100644
--- a/mruby/include/mruby/version.h
+++ b/mruby/include/mruby/version.h
@@ -27,7 +27,7 @@ MRB_BEGIN_DECL
/*
* The version of Ruby used by mruby.
*/
-#define MRUBY_RUBY_VERSION "3.2"
+#define MRUBY_RUBY_VERSION "3.3"
/*
* Ruby engine.
@@ -42,7 +42,7 @@ MRB_BEGIN_DECL
/*
* Minor release version number.
*/
-#define MRUBY_RELEASE_MINOR 2
+#define MRUBY_RELEASE_MINOR 3
/*
* Tiny release version number.
@@ -80,7 +80,7 @@ MRB_BEGIN_DECL
/*
* Release year.
*/
-#define MRUBY_RELEASE_YEAR 2023
+#define MRUBY_RELEASE_YEAR 2024
/*
* Release month.
@@ -90,7 +90,7 @@ MRB_BEGIN_DECL
/*
* Release day.
*/
-#define MRUBY_RELEASE_DAY 24
+#define MRUBY_RELEASE_DAY 14
/*
* Release date as a string.
diff --git a/mruby/lib/mruby/gem.rb b/mruby/lib/mruby/gem.rb
index 35aa2bd5..a2b649d7 100644
--- a/mruby/lib/mruby/gem.rb
+++ b/mruby/lib/mruby/gem.rb
@@ -372,6 +372,7 @@ def initialize
def each(&b)
@ary.each(&b)
+ self
end
def [](name)
@@ -384,6 +385,7 @@ def <<(gem)
else
# GEM was already added to this list
end
+ self
end
def empty?
diff --git a/mruby/mrbgems/mruby-bigint/README-fgmp.md b/mruby/mrbgems/mruby-bigint/README-fgmp.md
index 24e131ba..7693f3c1 100644
--- a/mruby/mrbgems/mruby-bigint/README-fgmp.md
+++ b/mruby/mrbgems/mruby-bigint/README-fgmp.md
@@ -56,7 +56,7 @@ Thanks also to Erick Gallesio for a fix
to mpz_init_set_str
Define B64 if your "long" type is 64 bits. Otherwise we assume 32
-bit longs. (The 64 bit version hasn't been tested enough)
+bit longs. (The 64-bit version hasn't been tested enough)
```
Platforms:
@@ -73,18 +73,18 @@ MS-DOS 286 C compiler (see credits above)
1. fgmp is considerably slower than gmp
2. fgmp does not implement the following:
- all mpq_*
- internal mpn_* functions
- mpz_perfect_square_p
- mpz_inp_raw, mpz_out_raw
- mp_set_memory_functions, mpz_out_str, mpz_inp_str
+ - all mpq\_\*
+ - internal mpn\_\* functions
+ - mpz_perfect_square_p
+ - mpz_inp_raw, mpz_out_raw
+ - mp_set_memory_functions, mpz_out_str, mpz_inp_str
3. fgmp implements the following in addition to the routines in GNU gmp.
- `int mpz_jacobi(MP_INT *a, MP_INT *b)`
- - finds the jacobi symbol (a/b)
+ `int mpz_jacobi(MP_INT *a, MP_INT *b)`
+ - finds the jacobi symbol (a/b)
4. mpz_sizeinbase often overestimates the exact value
5. To convert your gmp based program to fgmp (subject to the
-above)
+ above)
- recompile your source. Make sure to include the gmp.h file included
with fgmp rather than that included with gmp. (The point is to recompile
diff --git a/mruby/mrbgems/mruby-bigint/core/bigint.c b/mruby/mrbgems/mruby-bigint/core/bigint.c
index 97f54547..8877ab7e 100644
--- a/mruby/mrbgems/mruby-bigint/core/bigint.c
+++ b/mruby/mrbgems/mruby-bigint/core/bigint.c
@@ -478,7 +478,6 @@ udiv(mrb_state *mrb, mpz_t *qq, mpz_t *rr, mpz_t *xx, mpz_t *yy)
}
mpz_t q, x, y;
- size_t i;
mrb_assert(!uzero(yy)); /* divided by zero */
mpz_init(mrb, &q);
@@ -502,6 +501,8 @@ udiv(mrb_state *mrb, mpz_t *qq, mpz_t *rr, mpz_t *xx, mpz_t *yy)
else
qhat = (((mp_dbl_limb)x.p[j+yd] << DIG_SIZE) + x.p[j+yd-1]) / z;
if (qhat) {
+ size_t i;
+
for (i=0; i= b; rn++)
x *= bi;
@@ -1119,7 +1119,7 @@ mrb_bint_new_float(mrb_state *mrb, mrb_float x)
mpz_realloc(mrb, r, rn);
rp = r->p;
for (size_t i=rn-1;;i--) {
- f = LOW((mp_limb)x);
+ mp_limb f = LOW((mp_limb)x);
x -= f;
mrb_assert(x < 1.0);
rp[i] = f;
diff --git a/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
index 10522011..bf201ded 100644
--- a/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
+++ b/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
@@ -98,8 +98,8 @@ options_opt(struct options *opts)
while (++opts->argv, --opts->argc) {
opts->opt = *opts->argv;
- /* empty || not start with `-` || `-` */
- if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
+ /* not start with `-` || `-` */
+ if (opts->opt[0] != '-' || !opts->opt[1]) return NULL;
if (opts->opt[1] == '-') {
/* `--` */
@@ -278,10 +278,8 @@ main(int argc, char **argv)
{
mrb_state *mrb = mrb_open();
int n = -1;
- int i;
struct _args args;
mrb_value ARGV;
- mrb_ccontext *c;
mrb_value v;
if (mrb == NULL) {
@@ -297,7 +295,7 @@ main(int argc, char **argv)
else {
int ai = mrb_gc_arena_save(mrb);
ARGV = mrb_ary_new_capa(mrb, args.argc);
- for (i = 0; i < args.argc; i++) {
+ for (int i = 0; i < args.argc; i++) {
char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
if (utf8) {
mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
@@ -307,7 +305,7 @@ main(int argc, char **argv)
mrb_define_global_const(mrb, "ARGV", ARGV);
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
- c = mrb_ccontext_new(mrb);
+ mrb_ccontext *c = mrb_ccontext_new(mrb);
if (args.verbose)
c->dump_result = TRUE;
if (args.check_syntax)
@@ -324,7 +322,7 @@ main(int argc, char **argv)
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$0"), mrb_str_new_cstr(mrb, cmdline));
/* Load libraries */
- for (i = 0; i < args.libc; i++) {
+ for (int i = 0; i < args.libc; i++) {
FILE *lfp = fopen(args.libv[i], "rb");
if (lfp == NULL) {
fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]);
@@ -334,10 +332,10 @@ main(int argc, char **argv)
}
mrb_ccontext_filename(mrb, c, args.libv[i]);
if (mrb_extension_p(args.libv[i])) {
- v = mrb_load_irep_file_cxt(mrb, lfp, c);
+ mrb_load_irep_file_cxt(mrb, lfp, c);
}
else {
- v = mrb_load_detect_file_cxt(mrb, lfp, c);
+ mrb_load_detect_file_cxt(mrb, lfp, c);
}
fclose(lfp);
mrb_vm_ci_env_clear(mrb, mrb->c->cibase);
diff --git a/mruby/mrbgems/mruby-binding/src/binding.c b/mruby/mrbgems/mruby-binding/src/binding.c
index 7a0a577f..c269facf 100644
--- a/mruby/mrbgems/mruby-binding/src/binding.c
+++ b/mruby/mrbgems/mruby-binding/src/binding.c
@@ -106,15 +106,17 @@ binding_env_new_lvspace(mrb_state *mrb, const struct REnv *e)
return env;
}
-static size_t
-binding_proc_upper_count(const struct RProc *proc)
+static void
+binding_check_proc_upper_count(mrb_state *mrb, const struct RProc *proc)
{
- size_t count = 0;
- for (; proc && !MRB_PROC_CFUNC_P(proc); proc = proc->upper) {
+ for (size_t count = 0; proc && !MRB_PROC_CFUNC_P(proc); proc = proc->upper) {
count++;
+ if (count > BINDING_UPPER_MAX) {
+ mrb_raise(mrb, E_RUNTIME_ERROR,
+ "too many upper procs for local variables (mruby limitation; maximum is " MRB_STRINGIZE(BINDING_UPPER_MAX) ")");
+ }
if (MRB_PROC_SCOPE_P(proc)) break;
}
- return count;
}
mrb_bool
@@ -166,10 +168,7 @@ binding_initialize_copy(mrb_state *mrb, mrb_value binding)
lvspace = binding_wrap_lvspace(mrb, src_proc->upper, &env);
}
else {
- if (binding_proc_upper_count(src_proc) > BINDING_UPPER_MAX) {
- mrb_raise(mrb, E_RUNTIME_ERROR,
- "too many upper procs for local variables (mruby limitation; maximum is " MRB_STRINGIZE(BINDING_UPPER_MAX) ")");
- }
+ binding_check_proc_upper_count(mrb, src_proc);
env = src_env;
lvspace = binding_wrap_lvspace(mrb, src_proc, &env);
@@ -398,7 +397,8 @@ void
mrb_mruby_binding_gem_init(mrb_state *mrb)
{
struct RClass *binding = mrb_define_class(mrb, "Binding", mrb->object_class);
- MRB_SET_INSTANCE_TT(binding, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(binding, MRB_TT_OBJECT);
+ MRB_UNDEF_ALLOCATOR(binding);
mrb_undef_class_method(mrb, binding, "new");
mrb_undef_class_method(mrb, binding, "allocate");
diff --git a/mruby/mrbgems/mruby-complex/src/complex.c b/mruby/mrbgems/mruby-complex/src/complex.c
index f0e5829d..8aad4c00 100644
--- a/mruby/mrbgems/mruby-complex/src/complex.c
+++ b/mruby/mrbgems/mruby-complex/src/complex.c
@@ -149,12 +149,6 @@ mrb_complex_to_i(mrb_state *mrb, mrb_value self)
return mrb_int_value(mrb, (mrb_int)p->real);
}
-static mrb_value
-complex_to_c(mrb_state *mrb, mrb_value self)
-{
- return self;
-}
-
mrb_bool
mrb_complex_eq(mrb_state *mrb, mrb_value x, mrb_value y)
{
@@ -395,7 +389,8 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb)
struct RClass *comp;
comp = mrb_define_class_id(mrb, MRB_SYM(Complex), mrb_class_get_id(mrb, MRB_SYM(Numeric)));
- MRB_SET_INSTANCE_TT(comp, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(comp, MRB_TT_COMPLEX);
+ MRB_UNDEF_ALLOCATOR(comp);
mrb_undef_class_method(mrb, comp, "new");
mrb_define_class_method(mrb, comp, "rectangular", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
@@ -405,7 +400,7 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb)
mrb_define_method(mrb, comp, "imaginary", complex_imaginary, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "to_f", mrb_complex_to_f, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "to_i", mrb_complex_to_i, MRB_ARGS_NONE());
- mrb_define_method(mrb, comp, "to_c", complex_to_c, MRB_ARGS_NONE());
+ mrb_define_method(mrb, comp, "to_c", mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "+", complex_add, MRB_ARGS_REQ(1));
mrb_define_method(mrb, comp, "-", complex_sub, MRB_ARGS_REQ(1));
mrb_define_method(mrb, comp, "*", complex_mul, MRB_ARGS_REQ(1));
diff --git a/mruby/mrbgems/mruby-data/src/data.c b/mruby/mrbgems/mruby-data/src/data.c
index dd077619..46f3c025 100644
--- a/mruby/mrbgems/mruby-data/src/data.c
+++ b/mruby/mrbgems/mruby-data/src/data.c
@@ -228,6 +228,7 @@ make_data_class(mrb_state *mrb, mrb_value members, struct RClass *klass)
{
struct RClass *c = mrb_class_new(mrb, klass);
MRB_SET_INSTANCE_TT(c, MRB_TT_STRUCT);
+ MRB_DEFINE_ALLOCATOR(c);
mrb_value data = mrb_obj_value(c);
mrb_iv_set(mrb, data, MRB_SYM(__members__), members);
@@ -492,7 +493,8 @@ mrb_mruby_data_gem_init(mrb_state* mrb)
{
struct RClass *d;
d = mrb_define_class(mrb, "Data", mrb->object_class);
- MRB_SET_INSTANCE_TT(d, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(d, MRB_TT_STRUCT);
+ MRB_UNDEF_ALLOCATOR(d);
mrb_undef_class_method(mrb, d, "new");
mrb_define_class_method(mrb, d, "define", mrb_data_s_def, MRB_ARGS_ANY());
diff --git a/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb
index 2c9e8d3a..28562a1b 100644
--- a/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb
+++ b/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb
@@ -840,6 +840,17 @@ def filter_map(&blk)
alias filter select
+ def grep_v(pattern, &block)
+ ary = []
+ self.each{|*val|
+ sv = val.__svalue
+ unless pattern === sv
+ ary.push((block)? block.call(*val): sv)
+ end
+ }
+ ary
+ end
+
##
# call-seq:
# enum.tally -> a_hash
diff --git a/mruby/mrbgems/mruby-enum-ext/test/enum.rb b/mruby/mrbgems/mruby-enum-ext/test/enum.rb
index 31181fe1..98ace670 100644
--- a/mruby/mrbgems/mruby-enum-ext/test/enum.rb
+++ b/mruby/mrbgems/mruby-enum-ext/test/enum.rb
@@ -195,3 +195,10 @@ def each
assert("Enumerable#tally") do
assert_equal({"a"=>1, "b"=>2, "c"=>1}, ["a", "b", "c", "b"].tally)
end
+
+assert("Enumerable#grep_v") do
+ a = [1, 2, 3, 4, 5, 0]
+ assert_equal [1, 5, 0], a.grep_v(2..4)
+ assert_equal [1, 2, 3, 4, 5, 0], a.grep_v(6..8)
+ assert_equal [2, 4, 6, 8, 10], a.grep_v(0) {|v| v * 2}
+end
diff --git a/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb
index faaabf18..44d84865 100644
--- a/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb
+++ b/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb
@@ -701,4 +701,72 @@ def zip(*args, &block)
result
end
+
+ ##
+ # call-seq:
+ # enum.chunk -> enumerator
+ # enum.chunk { |arr| block } -> enumerator
+ #
+ # Each element in the returned enumerator is a 2-element array consisting of:
+ #
+ # - A value returned by the block.
+ # - An array ("chunk") containing the element for which that value was returned,
+ # and all following elements for which the block returned the same value:
+ #
+ # So that:
+ #
+ # - Each block return value that is different from its predecessor
+ # begins a new chunk.
+ # - Each block return value that is the same as its predecessor
+ # continues the same chunk.
+ #
+ # Example:
+ #
+ # e = (0..10).chunk {|i| (i / 3).floor } # => #
+ # # The enumerator elements.
+ # e.next # => [0, [0, 1, 2]]
+ # e.next # => [1, [3, 4, 5]]
+ # e.next # => [2, [6, 7, 8]]
+ # e.next # => [3, [9, 10]]
+ #
+ # You can use the special symbol :_alone to force an element
+ # into its own separate chuck:
+ #
+ # a = [0, 0, 1, 1]
+ # e = a.chunk{|i| i.even? ? :_alone : true }
+ # e.to_a # => [[:_alone, [0]], [:_alone, [0]], [true, [1, 1]]]
+ #
+ # You can use the special symbol :_separator or +nil+
+ # to force an element to be ignored (not included in any chunk):
+ #
+ # a = [0, 0, -1, 1, 1]
+ # e = a.chunk{|i| i < 0 ? :_separator : true }
+ # e.to_a # => [[true, [0, 0]], [true, [1, 1]]]
+ def chunk(&block)
+ return to_enum :chunk unless block
+
+ enum = self
+ Enumerator.new do |y|
+ last_value, arr = nil, []
+ enum.each do |element|
+ value = block.call(element)
+ case value
+ when :_alone
+ y.yield [last_value, arr] if arr.size > 0
+ y.yield [value, [element]]
+ last_value, arr = nil, []
+ when :_separator, nil
+ y.yield [last_value, arr] if arr.size > 0
+ last_value, arr = nil, []
+ when last_value
+ arr << element
+ else
+ raise 'symbols beginning with an underscore are reserved' if value.is_a?(Symbol) && value.to_s[0] == '_'
+ y.yield [last_value, arr] if arr.size > 0
+ last_value, arr = value, [element]
+ end
+ end
+ y.yield [last_value, arr] if arr.size > 0
+ end
+ end
end
diff --git a/mruby/mrbgems/mruby-enumerator/test/enumerator.rb b/mruby/mrbgems/mruby-enumerator/test/enumerator.rb
index 3e0c6c3b..4baf20c2 100644
--- a/mruby/mrbgems/mruby-enumerator/test/enumerator.rb
+++ b/mruby/mrbgems/mruby-enumerator/test/enumerator.rb
@@ -598,3 +598,52 @@ def (o = Object.new).each
], enum.to_a
}
end
+
+assert("Enumerable#chunk") do
+ chunk = [1, 2, 3, 1, 2].chunk
+ assert_equal Enumerator, chunk.class
+ result = chunk.with_index { |elt, i| elt - i }.to_a
+ assert_equal [[1, [1, 2, 3]], [-2, [1, 2]]], result
+
+ assert_equal Enumerator, [].chunk {}.class
+
+ e = [1, 2, 3]
+ recorded = []
+ e.chunk { |x| recorded << x }.to_a
+ assert_equal [1, 2, 3], recorded
+
+ e = [1, 2, 3, 2, 3, 2, 1]
+ result = e.chunk { |x| x < 3 && 1 || 0 }.to_a
+ assert_equal [[1, [1, 2]], [0, [3]], [1, [2]], [0, [3]], [1, [2, 1]]], result
+
+ e = [1, 2, 3]
+ assert_equal [[1, 2], [3]], e.chunk { |x| x > 2 }.map(&:last)
+
+ e = [1, 2, 3, 2, 1]
+ result = e.chunk { |x| x < 2 && :_alone }.to_a
+ assert_equal [[:_alone, [1]], [false, [2, 3, 2]], [:_alone, [1]]], result
+
+ e = [[1, 2]]
+ inner_value = []
+ e.chunk { |*x| inner_value << x }.to_a
+ assert_equal [[[1, 2]]], inner_value
+
+ e = [1, 2, 3, 3, 2, 1]
+ result = e.chunk { |x| x == 2 ? :_separator : 1 }.to_a
+ assert_equal [[1, [1]], [1, [3, 3]], [1, [1]]], result
+
+ e = [1, 2, 3, 2, 1]
+ result = e.chunk { |x| x == 2 ? nil : 1 }.to_a
+ assert_equal [[1, [1]], [1, [3]], [1, [1]]], result
+
+
+ e = [1, 2, 3, 2, 1]
+ assert_raise(RuntimeError) { e.chunk { |x| :_arbitrary }.to_a }
+
+ e = [1, 2, 3]
+ assert_raise(ArgumentError) { e.chunk(1) {} }
+
+ e = [1, 2, 3, 2, 1]
+ enum = e.chunk { |x| true }
+ assert_nil enum.size
+end
diff --git a/mruby/mrbgems/mruby-errno/src/errno.c b/mruby/mrbgems/mruby-errno/src/errno.c
index b2059f46..71ab61e2 100644
--- a/mruby/mrbgems/mruby-errno/src/errno.c
+++ b/mruby/mrbgems/mruby-errno/src/errno.c
@@ -288,7 +288,6 @@ mrb_sce_sys_fail(mrb_state *mrb, mrb_value cls)
if (argc == 1) {
msg = mrb_nil_value();
}
- exc = mrb_obj_value(e);
mrb_sce_init(mrb, exc, msg, no);
mrb_exc_raise(mrb, exc);
return mrb_nil_value(); /* NOTREACHED */
diff --git a/mruby/mrbgems/mruby-eval/src/eval.c b/mruby/mrbgems/mruby-eval/src/eval.c
index fe164582..db9b439b 100644
--- a/mruby/mrbgems/mruby-eval/src/eval.c
+++ b/mruby/mrbgems/mruby-eval/src/eval.c
@@ -344,8 +344,8 @@ mrb_mruby_eval_gem_init(mrb_state* mrb)
{
mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3));
mrb_define_method_id(mrb, mrb_class_get_id(mrb, MRB_SYM(BasicObject)), MRB_SYM(instance_eval), f_instance_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
- mrb_define_method_id(mrb, mrb_class_get_id(mrb, MRB_SYM(Module)), MRB_SYM(module_eval), f_class_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
- mrb_define_method_id(mrb, mrb_class_get_id(mrb, MRB_SYM(Module)), MRB_SYM(class_eval), f_class_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
+ mrb_define_method_id(mrb, mrb->module_class, MRB_SYM(module_eval), f_class_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
+ mrb_define_method_id(mrb, mrb->module_class, MRB_SYM(class_eval), f_class_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
struct RClass *binding = mrb_class_get_id(mrb, MRB_SYM(Binding));
mrb_define_method(mrb, binding, "eval", mrb_binding_eval, MRB_ARGS_ANY());
diff --git a/mruby/mrbgems/mruby-fiber/src/fiber.c b/mruby/mrbgems/mruby-fiber/src/fiber.c
index baddf65c..c0fd4d75 100644
--- a/mruby/mrbgems/mruby-fiber/src/fiber.c
+++ b/mruby/mrbgems/mruby-fiber/src/fiber.c
@@ -43,12 +43,12 @@ fiber_init_fiber(mrb_state *mrb, struct RFiber *f, const struct RProc *p)
c->stend = c->stbase + slen;
{
- mrb_value *p = c->stbase;
- mrb_value *pend = c->stend;
+ mrb_value *s = c->stbase;
+ mrb_value *send = c->stend;
- while (p < pend) {
- SET_NIL_VALUE(*p);
- p++;
+ while (s < send) {
+ SET_NIL_VALUE(*s);
+ s++;
}
}
@@ -252,8 +252,6 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
}
fiber_switch_context(mrb, c);
if (status == MRB_FIBER_CREATED) {
- mrb_value *b, *e;
-
if (!c->ci->proc) {
return fiber_error(mrb, "double resume (current)");
}
@@ -267,8 +265,10 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
}
else {
mrb_stack_extend(mrb, len+2); /* for receiver and (optional) block */
- b = c->stbase+1;
- e = b + len;
+
+ mrb_value *b = c->stbase+1;
+ mrb_value *e = b + len;
+
while (b
| method | mruby-io | memo |
-|----------------------------|----------|----------|
+| -------------------------- | -------- | -------- |
| IO.binread | | |
| IO.binwrite | | |
| IO.copy_stream | | |
@@ -102,7 +102,7 @@ Add the line below to your build configuration.
-
| method | mruby-io | memo |
-|-----------------------------|----------|----------|
+| --------------------------- | -------- | -------- |
| File.absolute_path | | |
| File.atime | | |
| File.basename | o | |
diff --git a/mruby/mrbgems/mruby-io/include/mruby/ext/io.h b/mruby/mrbgems/mruby-io/include/mruby/ext/io.h
index 13da769c..a0f3a2e8 100644
--- a/mruby/mrbgems/mruby-io/include/mruby/ext/io.h
+++ b/mruby/mrbgems/mruby-io/include/mruby/ext/io.h
@@ -6,6 +6,7 @@
#define MRUBY_IO_H
#include
+#include
#ifdef MRB_NO_STDIO
# error IO and File conflicts 'MRB_NO_STDIO' in your build configuration
@@ -63,8 +64,8 @@ struct mrb_io {
#define MRB_O_DSYNC 0x00008000
#define MRB_O_RSYNC 0x00010000
-#define E_IO_ERROR (mrb_exc_get(mrb, "IOError"))
-#define E_EOF_ERROR (mrb_exc_get(mrb, "EOFError"))
+#define E_IO_ERROR mrb_exc_get_id(mrb, MRB_SYM(IOError))
+#define E_EOF_ERROR mrb_exc_get_id(mrb, MRB_SYM(EOFError))
int mrb_io_fileno(mrb_state *mrb, mrb_value io);
diff --git a/mruby/mrbgems/mruby-io/src/file.c b/mruby/mrbgems/mruby-io/src/file.c
index 2bfef303..4116d477 100644
--- a/mruby/mrbgems/mruby-io/src/file.c
+++ b/mruby/mrbgems/mruby-io/src/file.c
@@ -120,15 +120,13 @@ mrb_file_s_unlink(mrb_state *mrb, mrb_value obj)
{
const mrb_value *argv;
mrb_int argc, i;
- char *path;
mrb_get_args(mrb, "*", &argv, &argc);
for (i = 0; i < argc; i++) {
- const char *utf8_path;
mrb_value pathv = argv[i];
mrb_ensure_string_type(mrb, pathv);
- utf8_path = RSTRING_CSTR(mrb, pathv);
- path = mrb_locale_from_utf8(utf8_path, -1);
+ const char *utf8_path = RSTRING_CSTR(mrb, pathv);
+ char *path = mrb_locale_from_utf8(utf8_path, -1);
if (UNLINK(path) < 0) {
mrb_locale_free(path);
mrb_sys_fail(mrb, utf8_path);
diff --git a/mruby/mrbgems/mruby-io/src/io.c b/mruby/mrbgems/mruby-io/src/io.c
index f796cf66..265716cd 100644
--- a/mruby/mrbgems/mruby-io/src/io.c
+++ b/mruby/mrbgems/mruby-io/src/io.c
@@ -102,12 +102,11 @@ io_get_open_fptr(mrb_state *mrb, mrb_value io)
static void
io_set_process_status(mrb_state *mrb, pid_t pid, int status)
{
- struct RClass *c_process, *c_status;
+ struct RClass *c_status = NULL;
mrb_value v;
- c_status = NULL;
if (mrb_class_defined_id(mrb, MRB_SYM(Process))) {
- c_process = mrb_module_get_id(mrb, MRB_SYM(Process));
+ struct RClass *c_process = mrb_module_get_id(mrb, MRB_SYM(Process));
if (mrb_const_defined(mrb, mrb_obj_value(c_process), MRB_SYM(Status))) {
c_status = mrb_class_get_under_id(mrb, c_process, MRB_SYM(Status));
}
@@ -320,7 +319,7 @@ io_free(mrb_state *mrb, void *ptr)
}
static void
-io_buf_init(mrb_state *mrb, struct mrb_io *fptr)
+io_init_buf(mrb_state *mrb, struct mrb_io *fptr)
{
if (fptr->readable) {
fptr->buf = (struct mrb_io_buf*)mrb_malloc(mrb, sizeof(struct mrb_io_buf));
@@ -478,7 +477,7 @@ io_s_popen(mrb_state *mrb, mrb_value klass)
fptr->pid = pid;
fptr->readable = OPEN_READABLE_P(flags);
fptr->writable = OPEN_WRITABLE_P(flags);
- io_buf_init(mrb, fptr);
+ io_init_buf(mrb, fptr);
DATA_TYPE(io) = &mrb_io_type;
DATA_PTR(io) = fptr;
@@ -522,8 +521,6 @@ io_s_popen(mrb_state *mrb, mrb_value klass)
}
if (!doexec) {
- // XXX
- fflush(stdin);
fflush(stdout);
fflush(stderr);
}
@@ -587,7 +584,7 @@ io_s_popen(mrb_state *mrb, mrb_value klass)
fptr->pid = pid;
fptr->readable = OPEN_READABLE_P(flags);
fptr->writable = OPEN_WRITABLE_P(flags);
- io_buf_init(mrb, fptr);
+ io_init_buf(mrb, fptr);
DATA_TYPE(io) = &mrb_io_type;
DATA_PTR(io) = fptr;
@@ -649,7 +646,7 @@ io_init_copy(mrb_state *mrb, mrb_value copy)
fptr_copy->sync = fptr_orig->sync;
fptr_copy->is_socket = fptr_orig->is_socket;
- io_buf_init(mrb, fptr_copy);
+ io_init_buf(mrb, fptr_copy);
DATA_TYPE(copy) = &mrb_io_type;
DATA_PTR(copy) = fptr_copy;
@@ -680,6 +677,7 @@ check_file_descriptor(mrb_state *mrb, mrb_int fd)
#if MRB_INT_MIN < INT_MIN || MRB_INT_MAX > INT_MAX
if (fdi != fd) {
+ errno = EBADF;
goto badfd;
}
#endif
@@ -695,6 +693,7 @@ check_file_descriptor(mrb_state *mrb, mrb_int fd)
}
if (fdi < 0 || fdi > _getmaxstdio()) {
+ errno = EBADF;
goto badfd;
}
#endif /* _WIN32 */
@@ -745,7 +744,7 @@ io_init(mrb_state *mrb, mrb_value io)
fptr->fd = (int)fd;
fptr->readable = OPEN_READABLE_P(flags);
fptr->writable = OPEN_WRITABLE_P(flags);
- io_buf_init(mrb, fptr);
+ io_init_buf(mrb, fptr);
return io;
}
@@ -1221,26 +1220,22 @@ time2timeval(mrb_state *mrb, mrb_value time)
static mrb_value
io_s_pipe(mrb_state *mrb, mrb_value klass)
{
- mrb_value r = mrb_nil_value();
- mrb_value w = mrb_nil_value();
- struct mrb_io *fptr_r;
- struct mrb_io *fptr_w;
int pipes[2];
if (io_pipe(mrb, pipes) == -1) {
mrb_sys_fail(mrb, "pipe");
}
- r = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
- fptr_r = io_alloc(mrb);
+ mrb_value r = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
+ struct mrb_io *fptr_r = io_alloc(mrb);
fptr_r->fd = pipes[0];
fptr_r->readable = 1;
DATA_TYPE(r) = &mrb_io_type;
DATA_PTR(r) = fptr_r;
- io_buf_init(mrb, fptr_r);
+ io_init_buf(mrb, fptr_r);
- w = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
- fptr_w = io_alloc(mrb);
+ mrb_value w = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
+ struct mrb_io *fptr_w = io_alloc(mrb);
fptr_w->fd = pipes[1];
fptr_w->writable = 1;
fptr_w->sync = 1;
@@ -1593,19 +1588,15 @@ io_ungetc(mrb_state *mrb, mrb_value io)
}
static void
-io_buf_reset(struct mrb_io *fptr)
+io_buf_reset(struct mrb_io_buf *buf)
{
- struct mrb_io_buf *buf = fptr->buf;
-
buf->start = 0;
buf->len = 0;
}
static void
-io_buf_shift(struct mrb_io *fptr, mrb_int n)
+io_buf_shift(struct mrb_io_buf *buf, mrb_int n)
{
- struct mrb_io_buf *buf = fptr->buf;
-
mrb_assert(n <= SHRT_MAX);
buf->start += (short)n;
buf->len -= (short)n;
@@ -1613,7 +1604,7 @@ io_buf_shift(struct mrb_io *fptr, mrb_int n)
#ifdef MRB_UTF8_STRING
static void
-io_buf_fill_comp(mrb_state *mrb, struct mrb_io *fptr)
+io_fill_buf_comp(mrb_state *mrb, struct mrb_io *fptr)
{
struct mrb_io_buf *buf = fptr->buf;
int keep = buf->len;
@@ -1628,7 +1619,7 @@ io_buf_fill_comp(mrb_state *mrb, struct mrb_io *fptr)
#endif
static void
-io_buf_fill(mrb_state *mrb, struct mrb_io *fptr)
+io_fill_buf(mrb_state *mrb, struct mrb_io *fptr)
{
struct mrb_io_buf *buf = fptr->buf;
@@ -1646,42 +1637,52 @@ io_eof(mrb_state *mrb, mrb_value io)
{
struct mrb_io *fptr = io_get_read_fptr(mrb, io);
- io_buf_fill(mrb, fptr);
+ if (fptr->eof) return mrb_true_value();
if (fptr->buf->len > 0) return mrb_false_value();
+ io_fill_buf(mrb, fptr);
return mrb_bool_value(fptr->eof);
}
static void
-io_buf_cat(mrb_state *mrb, mrb_value outbuf, struct mrb_io *fptr, mrb_int n)
+io_buf_cat(mrb_state *mrb, mrb_value outbuf, struct mrb_io_buf *buf, mrb_int n)
{
- struct mrb_io_buf *buf = fptr->buf;
-
mrb_assert(n <= buf->len);
mrb_str_cat(mrb, outbuf, buf->mem+buf->start, n);
- io_buf_shift(fptr, n);
+ io_buf_shift(buf, n);
}
static void
-io_buf_cat_all(mrb_state *mrb, mrb_value outbuf, struct mrb_io *fptr)
+io_buf_cat_all(mrb_state *mrb, mrb_value outbuf, struct mrb_io_buf *buf)
{
- struct mrb_io_buf *buf = fptr->buf;
-
mrb_str_cat(mrb, outbuf, buf->mem+buf->start, buf->len);
- io_buf_reset(fptr);
+ io_buf_reset(buf);
}
static mrb_value
io_read_all(mrb_state *mrb, struct mrb_io *fptr, mrb_value outbuf)
{
for (;;) {
- io_buf_fill(mrb, fptr);
+ io_fill_buf(mrb, fptr);
if (fptr->eof) {
return outbuf;
}
- io_buf_cat_all(mrb, outbuf, fptr);
+ io_buf_cat_all(mrb, outbuf, fptr->buf);
}
}
+static mrb_value
+io_reset_outbuf(mrb_state *mrb, mrb_value outbuf, mrb_int len)
+{
+ if (mrb_nil_p(outbuf)) {
+ outbuf = mrb_str_new(mrb, NULL, 0);
+ }
+ else {
+ mrb_str_modify(mrb, mrb_str_ptr(outbuf));
+ RSTR_SET_LEN(mrb_str_ptr(outbuf), 0);
+ }
+ return outbuf;
+}
+
static mrb_value
io_read(mrb_state *mrb, mrb_value io)
{
@@ -1702,30 +1703,31 @@ io_read(mrb_state *mrb, mrb_value io)
mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative length %d given", length);
}
if (length == 0) {
- return mrb_str_new(mrb, NULL, 0);
+ return io_reset_outbuf(mrb, outbuf, 0);
}
}
}
- if (mrb_nil_p(outbuf)) {
- outbuf = mrb_str_new_capa(mrb, MRB_IO_BUF_SIZE);
- }
+ outbuf = io_reset_outbuf(mrb, outbuf, MRB_IO_BUF_SIZE);
if (!length_given) { /* read as much as possible */
return io_read_all(mrb, fptr, outbuf);
}
+
+ struct mrb_io_buf *buf = fptr->buf;
+
for (;;) {
- io_buf_fill(mrb, fptr);
+ io_fill_buf(mrb, fptr);
if (fptr->eof || length == 0) {
if (RSTRING_LEN(outbuf) == 0)
return mrb_nil_value();
return outbuf;
}
- if (fptr->buf->len < length) {
- length -= fptr->buf->len;
- io_buf_cat_all(mrb, outbuf, fptr);
+ if (buf->len < length) {
+ length -= buf->len;
+ io_buf_cat_all(mrb, outbuf, buf);
}
else {
- io_buf_cat(mrb, outbuf, fptr, length);
+ io_buf_cat(mrb, outbuf, buf, length);
return outbuf;
}
}
@@ -1797,7 +1799,7 @@ io_gets(mrb_state *mrb, mrb_value io)
return io_read_all(mrb, fptr, mrb_str_new_capa(mrb, MRB_IO_BUF_SIZE));
}
- io_buf_fill(mrb, fptr);
+ io_fill_buf(mrb, fptr);
if (fptr->eof) return mrb_nil_value();
if (limit_given) {
@@ -1817,19 +1819,19 @@ io_gets(mrb_state *mrb, mrb_value io)
if (limit_given && limit < n) {
n = limit;
}
- io_buf_cat(mrb, outbuf, fptr, n);
+ io_buf_cat(mrb, outbuf, buf, n);
return outbuf;
}
}
if (limit_given) {
if (limit <= buf->len) {
- io_buf_cat(mrb, outbuf, fptr, limit);
+ io_buf_cat(mrb, outbuf, buf, limit);
return outbuf;
}
limit -= buf->len;
}
- io_buf_cat_all(mrb, outbuf, fptr);
- io_buf_fill(mrb, fptr);
+ io_buf_cat_all(mrb, outbuf, buf);
+ io_fill_buf(mrb, fptr);
if (fptr->eof) {
if (RSTRING_LEN(outbuf) == 0) return mrb_nil_value();
return outbuf;
@@ -1864,23 +1866,23 @@ io_getc(mrb_state *mrb, mrb_value io)
{
mrb_int len = 1;
struct mrb_io *fptr = io_get_read_fptr(mrb, io);
+ struct mrb_io_buf *buf = fptr->buf;
- io_buf_fill(mrb, fptr);
+ io_fill_buf(mrb, fptr);
if (fptr->eof) return mrb_nil_value();
#ifdef MRB_UTF8_STRING
- struct mrb_io_buf *buf = fptr->buf;
const char *p = &buf->mem[buf->start];
if ((*p) & 0x80) {
len = mrb_utf8len(p, p+buf->len);
if (len == 1 && buf->len < 4) { /* partial UTF-8 */
- io_buf_fill_comp(mrb, fptr);
+ io_fill_buf_comp(mrb, fptr);
p = &buf->mem[buf->start];
len = mrb_utf8len(p, p+buf->len);
}
}
#endif
- mrb_value str = mrb_str_new(mrb, fptr->buf->mem+fptr->buf->start, len);
- io_buf_shift(fptr, len);
+ mrb_value str = mrb_str_new(mrb, buf->mem+buf->start, len);
+ io_buf_shift(buf, len);
return str;
}
@@ -1898,12 +1900,13 @@ static mrb_value
io_getbyte(mrb_state *mrb, mrb_value io)
{
struct mrb_io *fptr = io_get_read_fptr(mrb, io);
+ struct mrb_io_buf *buf = fptr->buf;
- io_buf_fill(mrb, fptr);
+ io_fill_buf(mrb, fptr);
if (fptr->eof) return mrb_nil_value();
- unsigned char c = fptr->buf->mem[fptr->buf->start];
- io_buf_shift(fptr, 1);
+ unsigned char c = buf->mem[buf->start];
+ io_buf_shift(buf, 1);
return mrb_int_value(mrb, (mrb_int)c);
}
diff --git a/mruby/mrbgems/mruby-io/test/io.rb b/mruby/mrbgems/mruby-io/test/io.rb
index d146d6d8..811038ff 100644
--- a/mruby/mrbgems/mruby-io/test/io.rb
+++ b/mruby/mrbgems/mruby-io/test/io.rb
@@ -150,6 +150,30 @@ def assert_io_open(meth)
end
end
+assert "IO#read(n, buf)" do
+ IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|
+ buf = "12345"
+ assert_same buf, io.read(0, buf)
+ assert_equal "", buf
+
+ buf = "12345"
+ assert_same buf, io.read(5, buf)
+ assert_equal "mruby", buf
+
+ buf = "12345"
+ assert_same buf, io.read(nil, buf)
+ assert_equal " io test\n", buf
+
+ buf = "12345"
+ assert_nil io.read(99, buf)
+ assert_equal "", buf
+
+ buf = "12345"
+ assert_same buf, io.read(0, buf)
+ assert_equal "", buf
+ end
+end
+
assert('IO#readchar', '15.2.20.5.15') do
# almost same as IO#getc
IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|
diff --git a/mruby/mrbgems/mruby-kernel-ext/src/kernel.c b/mruby/mrbgems/mruby-kernel-ext/src/kernel.c
index 89116f63..6bdcc946 100644
--- a/mruby/mrbgems/mruby-kernel-ext/src/kernel.c
+++ b/mruby/mrbgems/mruby-kernel-ext/src/kernel.c
@@ -59,7 +59,7 @@ mrb_f_caller(mrb_state *mrb, mrb_value self)
if (n < 0) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative size (%d)", n);
}
- if (n == 0 || bt_len <= lev) {
+ if (n == 0) {
return mrb_ary_new(mrb);
}
if (bt_len <= n + lev) n = bt_len - lev - 1;
diff --git a/mruby/mrbgems/mruby-math/src/math.c b/mruby/mrbgems/mruby-math/src/math.c
index 75f0a220..0d2f4cc4 100644
--- a/mruby/mrbgems/mruby-math/src/math.c
+++ b/mruby/mrbgems/mruby-math/src/math.c
@@ -74,7 +74,7 @@ atanh(double x)
}
else {
/* Basic formula for atanh */
- y = 0.5 * (log(1.0+x) - log(1.0-x));
+ y = 0.5 * (log1p(x) - log1p(-x));
}
return y;
@@ -105,7 +105,7 @@ double erfc(double x);
double
erf(double x)
{
- static const double two_sqrtpi = 1.128379167095512574;
+ static const double two_sqrtpi = 1.128379167095512574;
double sum = x;
double term = x;
double xsqr = x*x;
@@ -129,7 +129,7 @@ erf(double x)
double
erfc(double x)
{
- static const double one_sqrtpi= 0.564189583547756287;
+ static const double one_sqrtpi = 0.564189583547756287;
double a = 1;
double b = x;
double c = x;
@@ -137,15 +137,15 @@ erfc(double x)
double q1;
double q2 = b/d;
double n = 1.0;
- double t;
+
if (fabs(x) < 2.2) {
- return 1.0 - erf(x);
+ return erfc(x);
}
if (x < 0.0) { /*signbit(x)*/
return 2.0 - erfc(-x);
}
do {
- t = a*n+b*x;
+ double t = a*n+b*x;
a = b;
b = t;
t = c*n+d*x;
diff --git a/mruby/mrbgems/mruby-metaprog/src/metaprog.c b/mruby/mrbgems/mruby-metaprog/src/metaprog.c
index 3b93574c..f1fe097c 100644
--- a/mruby/mrbgems/mruby-metaprog/src/metaprog.c
+++ b/mruby/mrbgems/mruby-metaprog/src/metaprog.c
@@ -176,7 +176,6 @@ static mrb_value
mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *klass)
{
mrb_value ary;
- struct RClass *oldklass;
khash_t(st) *set = kh_init(st, mrb);
if (!recur) {
@@ -187,8 +186,8 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *kl
}
else {
khash_t(st) *undef = kh_init(st, mrb);
+ struct RClass *oldklass = NULL;
- oldklass = NULL;
while (klass && (klass != oldklass)) {
method_entry_loop(mrb, klass, set, undef);
oldklass = klass;
diff --git a/mruby/mrbgems/mruby-method/src/method.c b/mruby/mrbgems/mruby-method/src/method.c
index deb37b4a..f12cc44b 100644
--- a/mruby/mrbgems/mruby-method/src/method.c
+++ b/mruby/mrbgems/mruby-method/src/method.c
@@ -546,7 +546,8 @@ mrb_mruby_method_gem_init(mrb_state* mrb)
struct RClass *unbound_method = mrb_define_class_id(mrb, MRB_SYM(UnboundMethod), mrb->object_class);
struct RClass *method = mrb_define_class_id(mrb, MRB_SYM(Method), mrb->object_class);
- MRB_SET_INSTANCE_TT(unbound_method, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(unbound_method, MRB_TT_OBJECT);
+ MRB_UNDEF_ALLOCATOR(unbound_method);
mrb_undef_class_method(mrb, unbound_method, "new");
mrb_define_method(mrb, unbound_method, "bind", unbound_method_bind, MRB_ARGS_REQ(1));
mrb_define_method(mrb, unbound_method, "super_method", method_super_method, MRB_ARGS_NONE());
@@ -561,7 +562,8 @@ mrb_mruby_method_gem_init(mrb_state* mrb)
mrb_define_method(mrb, unbound_method, "owner", method_owner, MRB_ARGS_NONE());
mrb_define_method(mrb, unbound_method, "name", method_name, MRB_ARGS_NONE());
- MRB_SET_INSTANCE_TT(method, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(method, MRB_TT_OBJECT);
+ MRB_UNDEF_ALLOCATOR(method);
mrb_undef_class_method(mrb, method, "new");
mrb_define_method(mrb, method, "==", method_eql, MRB_ARGS_REQ(1));
mrb_define_method(mrb, method, "eql?", method_eql, MRB_ARGS_REQ(1));
diff --git a/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c b/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c
index 4833f05f..097a902f 100644
--- a/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c
+++ b/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c
@@ -165,8 +165,7 @@ int_digits(mrb_state *mrb, mrb_value self)
}
while (mrb_bint_cmp(mrb, x, zero) > 0) {
- mrb_value q = mrb_bint_mod(mrb, x, bv);
- mrb_ary_push(mrb, digits, q);
+ mrb_ary_push(mrb, digits, mrb_bint_mod(mrb, x, bv));
x = mrb_bint_div(mrb, x, bv);
if (!mrb_bigint_p(x)) {
mrb_int n = mrb_integer(x);
diff --git a/mruby/mrbgems/mruby-object-ext/src/object.c b/mruby/mrbgems/mruby-object-ext/src/object.c
index f0b50bf1..62345810 100644
--- a/mruby/mrbgems/mruby-object-ext/src/object.c
+++ b/mruby/mrbgems/mruby-object-ext/src/object.c
@@ -60,6 +60,8 @@ nil_to_i(mrb_state *mrb, mrb_value obj)
}
/*
+ * Document-method: Kernel#itself
+ *
* call-seq:
* obj.itself -> an_object
*
@@ -69,11 +71,6 @@ nil_to_i(mrb_state *mrb, mrb_value obj)
* string.itself.object_id == string.object_id #=> true
*
*/
-static mrb_value
-f_itself(mrb_state *mrb, mrb_value self)
-{
- return self;
-}
/*
* call-seq:
@@ -122,7 +119,7 @@ mrb_mruby_object_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, n, "to_h", nil_to_h, MRB_ARGS_NONE());
mrb_define_method(mrb, n, "to_i", nil_to_i, MRB_ARGS_NONE());
- mrb_define_method(mrb, mrb->kernel_module, "itself", f_itself, MRB_ARGS_NONE());
+ mrb_define_method(mrb, mrb->kernel_module, "itself", mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method(mrb, mrb_class_get_id(mrb, MRB_SYM(BasicObject)), "instance_exec", obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK());
}
diff --git a/mruby/mrbgems/mruby-os-memsize/src/memsize.c b/mruby/mrbgems/mruby-os-memsize/src/memsize.c
index 10f77bee..8ffd313e 100644
--- a/mruby/mrbgems/mruby-os-memsize/src/memsize.c
+++ b/mruby/mrbgems/mruby-os-memsize/src/memsize.c
@@ -1,4 +1,5 @@
#include
+#include
#include
#include
#include
@@ -167,6 +168,9 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj)
case MRB_TT_ISTRUCT:
size += mrb_objspace_page_slot_size();
break;
+ case MRB_TT_BACKTRACE:
+ size += ((struct RBacktrace*)mrb_obj_ptr(obj))->len * sizeof(struct mrb_backtrace_location);
+ break;
/* zero heap size types.
* immediate VM stack values, contained within mrb_state, or on C stack */
case MRB_TT_TRUE:
diff --git a/mruby/mrbgems/mruby-pack/README.md b/mruby/mrbgems/mruby-pack/README.md
index 10a53809..2871fb4b 100644
--- a/mruby/mrbgems/mruby-pack/README.md
+++ b/mruby/mrbgems/mruby-pack/README.md
@@ -45,7 +45,9 @@ There is no dependency on other mrbgems.
- V : 32-bit unsigned, VAX (little-endian) byte order
- v : 16-bit unsigned, VAX (little-endian) byte order
- x : null byte
-- Z : same as "a", except that null is added with *
+- X : back up bytes
+- Z : same as "a", except that null is added with \*
+- @ : absolute position
## License
diff --git a/mruby/mrbgems/mruby-pack/src/pack.c b/mruby/mrbgems/mruby-pack/src/pack.c
index 08db9091..8f61b0bb 100644
--- a/mruby/mrbgems/mruby-pack/src/pack.c
+++ b/mruby/mrbgems/mruby-pack/src/pack.c
@@ -291,27 +291,24 @@ static void
u64tostr(char *buf, size_t len, uint64_t n)
{
#ifdef MRB_NO_STDIO
- char *bufend = buf + len;
- char *p = bufend - 1;
+ mrb_assert(len > 0);
- if (len < 1) {
+ if (n < 10) {
+ buf[0] = '0' + n;
+ buf[1] = '\0';
return;
}
+ char *bufend = buf + len;
+ char *p = bufend - 1;
+
*p-- = '\0';
len--;
- if (n > 0) {
- for (; len > 0 && n > 0; len--, n /= 10) {
- *p-- = '0' + (n % 10);
- }
- p++;
- }
- else if (len > 0) {
- *p = '0';
- len--;
+ for (; len > 0 && n > 0; len--, n /= 10) {
+ *p-- = '0' + (n % 10);
}
-
+ p++;
memmove(buf, p, bufend - p);
#else
snprintf(buf, len, "%" PRIu64, n);
@@ -323,9 +320,7 @@ static void
i64tostr(char *buf, size_t len, int64_t n)
{
#ifdef MRB_NO_STDIO
- if (len < 1) {
- return;
- }
+ mrb_assert(len > 0);
if (n < 0) {
*buf++ = '-';
@@ -731,7 +726,7 @@ unpack_str(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count,
CHECK_UNPACK_LEN(mrb, slen, ary);
mrb_value dst;
- const char *cp, *sptr;
+ const char *sptr;
int copylen;
sptr = (const char*)src;
@@ -741,6 +736,8 @@ unpack_str(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count,
copylen = slen;
if (slen >= 0 && flags & PACK_FLAG_Z) { /* "Z" */
+ const char *cp;
+
if ((cp = (const char*)memchr(sptr, '\0', slen)) != NULL) {
copylen = (int)(cp - sptr);
if (count == -1) {
@@ -764,7 +761,6 @@ unpack_str(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count,
static int
pack_hex(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, int count, unsigned int flags)
{
- int a, b;
unsigned int ashift, bshift;
long slen;
char *dptr, *dptr0, *sptr;
@@ -793,7 +789,8 @@ pack_hex(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, int count,
dptr0 = dptr;
for (; count > 0; count -= 2) {
- a = b = 0;
+ int a = 0, b = 0;
+
if (slen > 0) {
a = hex2int(*sptr++);
if (a < 0) break;
@@ -1498,19 +1495,17 @@ static mrb_value
mrb_pack_pack(mrb_state *mrb, mrb_value ary)
{
mrb_value o, result;
- mrb_int aidx;
struct tmpl tmpl;
- int count;
+ enum pack_type type;
+ int count, size;
unsigned int flags;
enum pack_dir dir;
- enum pack_type type;
- int ridx, size;
prepare_tmpl(mrb, &tmpl);
result = mrb_str_new(mrb, NULL, 128); /* allocate initial buffer */
- aidx = 0;
- ridx = 0;
+ mrb_int aidx = 0;
+ mrb_int ridx = 0;
while (has_tmpl(&tmpl)) {
dir = read_tmpl(mrb, &tmpl, &type, &size, &count, &flags);
@@ -1667,18 +1662,23 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)
switch (dir) {
case PACK_DIR_HEX:
srcidx += unpack_hex(mrb, sptr, srclen - srcidx, result, count, flags);
+ if (single) goto single_return;
continue;
case PACK_DIR_BSTR:
srcidx += unpack_bstr(mrb, sptr, srclen - srcidx, result, count, flags);
+ if (single) goto single_return;
continue;
case PACK_DIR_STR:
srcidx += unpack_str(mrb, sptr, srclen - srcidx, result, count, flags);
+ if (single) goto single_return;
continue;
case PACK_DIR_BASE64:
srcidx += unpack_base64(mrb, sptr, srclen - srcidx, result);
+ if (single) goto single_return;
continue;
case PACK_DIR_QENC:
srcidx += unpack_qenc(mrb, sptr, srclen - srcidx, result);
+ if (single) goto single_return;
continue;
default:
break;
@@ -1727,12 +1727,13 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)
count--;
}
}
- if (single) {
- if (RARRAY_LEN(result) > 0) {
- return RARRAY_PTR(result)[0];
- }
- return mrb_nil_value();
+ }
+ if (single) {
+ single_return:
+ if (RARRAY_LEN(result) > 0) {
+ return RARRAY_PTR(result)[0];
}
+ return mrb_nil_value();
}
return result;
}
diff --git a/mruby/mrbgems/mruby-pack/test/pack.rb b/mruby/mrbgems/mruby-pack/test/pack.rb
index 6045f788..a3f110ba 100644
--- a/mruby/mrbgems/mruby-pack/test/pack.rb
+++ b/mruby/mrbgems/mruby-pack/test/pack.rb
@@ -156,3 +156,18 @@ def assert_pack tmpl, packed, unpacked
assert_raise(RangeError) { [-1].pack("U") }
assert_raise(RangeError) { [0x40000000].pack("U") }
end
+
+assert 'unpack1' do
+ d = 1234
+ assert_equal(d, [d].pack("i").unpack1("i"))
+ d = "foobar"
+ assert_equal(d, [d].pack("a*").unpack1("a*"))
+ assert_equal(d, [d].pack("A*").unpack1("A*"))
+ assert_equal(d, [d].pack("Z*").unpack1("Z*"))
+ assert_equal(d, [d].pack("m").unpack1("m"))
+ assert_equal(d, [d].pack("M").unpack1("M"))
+ d = "10010101"
+ assert_equal(d, [d].pack("b*").unpack1("b*"))
+ d = "f00b00"
+ assert_equal(d, [d].pack("h*").unpack1("h*"))
+end
diff --git a/mruby/mrbgems/mruby-random/src/random.c b/mruby/mrbgems/mruby-random/src/random.c
index c47702e9..98d4fce4 100644
--- a/mruby/mrbgems/mruby-random/src/random.c
+++ b/mruby/mrbgems/mruby-random/src/random.c
@@ -344,28 +344,27 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary)
}
else {
mrb_value result;
- mrb_int i, j;
if (n < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "negative sample number");
if (n > len) n = len;
result = mrb_ary_new_capa(mrb, n);
- for (i=0; inumerator / p->denominator);
}
-static mrb_value
-rational_to_r(mrb_state *mrb, mrb_value self)
-{
- return self;
-}
-
static mrb_value
rational_negative_p(mrb_state *mrb, mrb_value self)
{
@@ -702,9 +655,10 @@ rational_div(mrb_state *mrb, mrb_value x)
static mrb_value
rational_pow(mrb_state *mrb, mrb_value x)
{
+#ifndef MRB_NO_FLOAT
mrb_value y = mrb_get_arg1(mrb);
struct mrb_rational *p1 = rational_ptr(mrb, x);
-#ifndef MRB_NO_FLOAT
+
double d1, d2;
switch (mrb_type(y)) {
@@ -767,16 +721,16 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb)
struct RClass *rat;
rat = mrb_define_class_id(mrb, MRB_SYM(Rational), mrb_class_get_id(mrb, MRB_SYM(Numeric)));
- MRB_SET_INSTANCE_TT(rat, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(rat, MRB_TT_RATIONAL);
+ MRB_UNDEF_ALLOCATOR(rat);
mrb_undef_class_method(mrb, rat, "new");
- mrb_define_class_method(mrb, rat, "_new", rational_s_new, MRB_ARGS_REQ(2));
mrb_define_method(mrb, rat, "numerator", rational_numerator, MRB_ARGS_NONE());
mrb_define_method(mrb, rat, "denominator", rational_denominator, MRB_ARGS_NONE());
#ifndef MRB_NO_FLOAT
mrb_define_method(mrb, rat, "to_f", mrb_rational_to_f, MRB_ARGS_NONE());
#endif
mrb_define_method(mrb, rat, "to_i", mrb_rational_to_i, MRB_ARGS_NONE());
- mrb_define_method(mrb, rat, "to_r", rational_to_r, MRB_ARGS_NONE());
+ mrb_define_method(mrb, rat, "to_r", mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method(mrb, rat, "negative?", rational_negative_p, MRB_ARGS_NONE());
mrb_define_method(mrb, rat, "==", rational_eq, MRB_ARGS_REQ(1));
mrb_define_method(mrb, rat, "<=>", rational_cmp, MRB_ARGS_REQ(1));
diff --git a/mruby/mrbgems/mruby-string-ext/src/string.c b/mruby/mrbgems/mruby-string-ext/src/string.c
index 79b4743a..82a52863 100644
--- a/mruby/mrbgems/mruby-string-ext/src/string.c
+++ b/mruby/mrbgems/mruby-string-ext/src/string.c
@@ -53,7 +53,7 @@ int_chr_utf8(mrb_state *mrb, mrb_value num)
char utf8[4];
mrb_int len;
mrb_value str;
- uint32_t ascii_flag = 0;
+ uint32_t sb_flag = 0;
if (cp < 0 || 0x10FFFF < cp) {
mrb_raisef(mrb, E_RANGE_ERROR, "%v out of char range", num);
@@ -61,7 +61,7 @@ int_chr_utf8(mrb_state *mrb, mrb_value num)
if (cp < 0x80) {
utf8[0] = (char)cp;
len = 1;
- ascii_flag = MRB_STR_ASCII;
+ sb_flag = MRB_STR_SINGLE_BYTE;
}
else if (cp < 0x800) {
utf8[0] = (char)(0xC0 | (cp >> 6));
@@ -82,7 +82,7 @@ int_chr_utf8(mrb_state *mrb, mrb_value num)
len = 4;
}
str = mrb_str_new(mrb, utf8, len);
- mrb_str_ptr(str)->flags |= ascii_flag;
+ mrb_str_ptr(str)->flags |= sb_flag;
return str;
}
#endif
@@ -1304,10 +1304,6 @@ str_uplus(mrb_state *mrb, mrb_value str)
*
* Returns a frozen, possibly pre-existing copy of the string.
*
- * The returned \String will be deduplicated as long as it does not have
- * any instance variables set on it and is not a String subclass.
- *
- * String#dedup is an alias for String#-@.
*/
static mrb_value
str_uminus(mrb_state *mrb, mrb_value str)
@@ -1332,34 +1328,39 @@ str_valid_enc_p(mrb_state *mrb, mrb_value str)
#define utf8_islead(c) ((unsigned char)((c)&0xc0) != 0x80)
struct RString *s = mrb_str_ptr(str);
- if (RSTR_ASCII_P(s)) return mrb_true_value();
+ if (RSTR_SINGLE_BYTE_P(s)) return mrb_true_value();
mrb_int byte_len = RSTR_LEN(s);
mrb_int utf8_len = 0;
const char *p = RSTR_PTR(s);
const char *e = p + byte_len;
while (p < e) {
- mrb_int len = mrb_utf8len_table[(unsigned char)p[0] >> 3];
- if (len == 0 || len > e - p)
- return mrb_false_value();
- switch (len) {
- case 4:
- if (utf8_islead(p[3])) return mrb_false_value();
- case 3:
- if (utf8_islead(p[2])) return mrb_false_value();
- case 2:
- if (utf8_islead(p[1])) return mrb_false_value();
- default:
- break;
- }
+ mrb_int len = mrb_utf8len(p, e);
+
+ if (len == 1 && (*p & 0x80)) return mrb_false_value();
p += len;
utf8_len++;
}
- if (byte_len == utf8_len) RSTR_SET_ASCII_FLAG(s);
+ if (byte_len == utf8_len) RSTR_SET_SINGLE_BYTE_FLAG(s);
#endif
return mrb_true_value();
}
+static mrb_value
+str_ascii_only_p(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = mrb_str_ptr(str);
+ const char *p = RSTR_PTR(s);
+ const char *e = p + RSTR_LEN(s);
+
+ while (p < e) {
+ if (*p & 0x80) return mrb_false_value();
+ p++;
+ }
+ RSTR_SET_SINGLE_BYTE_FLAG(mrb_str_ptr(str));
+ return mrb_true_value();
+}
+
void
mrb_mruby_string_ext_gem_init(mrb_state* mrb)
{
@@ -1398,6 +1399,7 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, s, "+@", str_uplus, MRB_ARGS_REQ(1));
mrb_define_method(mrb, s, "-@", str_uminus, MRB_ARGS_REQ(1));
mrb_define_method(mrb, s, "valid_encoding?", str_valid_enc_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "ascii_only?", str_ascii_only_p, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "__lines", str_lines, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "__codepoints", str_codepoints, MRB_ARGS_NONE());
diff --git a/mruby/mrbgems/mruby-struct/src/struct.c b/mruby/mrbgems/mruby-struct/src/struct.c
index 4f6dadcf..a615607a 100644
--- a/mruby/mrbgems/mruby-struct/src/struct.c
+++ b/mruby/mrbgems/mruby-struct/src/struct.c
@@ -210,6 +210,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass *kl
c = mrb_define_class_under_id(mrb, klass, id, klass);
}
MRB_SET_INSTANCE_TT(c, MRB_TT_STRUCT);
+ MRB_DEFINE_ALLOCATOR(c);
nstr = mrb_obj_value(c);
mrb_iv_set(mrb, nstr, MRB_SYM(__members__), members);
@@ -697,7 +698,8 @@ mrb_mruby_struct_gem_init(mrb_state* mrb)
{
struct RClass *st;
st = mrb_define_class(mrb, "Struct", mrb->object_class);
- MRB_SET_INSTANCE_TT(st, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(st, MRB_TT_STRUCT);
+ MRB_UNDEF_ALLOCATOR(st);
mrb_define_class_method(mrb, st, "new", mrb_struct_s_def, MRB_ARGS_ANY()); /* 15.2.18.3.1 */
diff --git a/mruby/mrbgems/mruby-time/src/time.c b/mruby/mrbgems/mruby-time/src/time.c
index 001d46b7..59dcd80b 100644
--- a/mruby/mrbgems/mruby-time/src/time.c
+++ b/mruby/mrbgems/mruby-time/src/time.c
@@ -83,7 +83,8 @@ double round(double x) {
/** end of Time class configuration */
-#if (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(CLOCK_REALTIME)
+/* protection against incorrectly defined _POSIX_TIMERS */
+#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS + 0) > 0 && defined(CLOCK_REALTIME)
# define USE_CLOCK_GETTIME
#endif
diff --git a/mruby/src/allocf.c b/mruby/src/allocf.c
new file mode 100644
index 00000000..aa9ca646
--- /dev/null
+++ b/mruby/src/allocf.c
@@ -0,0 +1,30 @@
+/*
+** allocf.c - default memory allocation function
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include
+#include "mruby.h"
+
+/* This function serves as the default memory allocation function and accepts four arguments:
+ *
+ * - `mrb`: An instance of `mrb_state`. It's important to note that for the initial allocation (used to allocate the `mrb_state` itself), `mrb` is set to NULL.
+ * - `p`: The previous pointer to the memory region. For memory allocation, this parameter is NULL.
+ * - `size`: The new size of the memory region to be returned.
+ * - `ud`: User data, represented as a `void*`, which is passed to the `mrb_state`.
+ */
+
+void*
+mrb_default_allocf(mrb_state *mrb, void *p, size_t size, void *ud)
+{
+ if (size == 0) {
+ /* `free(NULL)` should be no-op */
+ free(p);
+ return NULL;
+ }
+ else {
+ /* `ralloc(NULL, size)` works as `malloc(size)` */
+ return realloc(p, size);
+ }
+}
diff --git a/mruby/src/array.c b/mruby/src/array.c
index 01ccd85a..7e2d03c6 100644
--- a/mruby/src/array.c
+++ b/mruby/src/array.c
@@ -215,18 +215,18 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
capa = len;
}
}
- if (capa < len || capa > ARY_MAX_SIZE) {
+ if (capa > ARY_MAX_SIZE) {
ary_too_big(mrb);
}
if (ARY_EMBED_P(a)) {
mrb_value *ptr = ARY_EMBED_PTR(a);
- mrb_int len = ARY_EMBED_LEN(a);
+ mrb_int slen = ARY_EMBED_LEN(a);
mrb_value *expanded_ptr = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*capa);
ARY_UNSET_EMBED_FLAG(a);
- array_copy(expanded_ptr, ptr, len);
- a->as.heap.len = len;
+ array_copy(expanded_ptr, ptr, slen);
+ a->as.heap.len = slen;
a->as.heap.aux.capa = capa;
a->as.heap.ptr = expanded_ptr;
}
diff --git a/mruby/src/backtrace.c b/mruby/src/backtrace.c
index 816b0e6d..636e3ce2 100644
--- a/mruby/src/backtrace.c
+++ b/mruby/src/backtrace.c
@@ -17,23 +17,30 @@
#include
#include
-struct backtrace_location {
- mrb_sym method_id;
- int32_t idx;
- const mrb_irep *irep;
-};
-
-typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*, void*);
-
-static const mrb_data_type bt_type = { "Backtrace", mrb_free };
+static void
+copy_backtrace(mrb_state *mrb,
+ const struct mrb_backtrace_location *loc,
+ struct mrb_backtrace_location *ptr,
+ size_t n)
+{
+ ptr[n] = *loc;
+ if (loc->irep) {
+ if (loc->irep->refcnt == UINT16_MAX) {
+ ptr[n].irep = NULL;
+ }
+ else {
+ mrb_irep_incref(mrb, (mrb_irep*)loc->irep);
+ }
+ }
+}
-static uint32_t
-each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, each_backtrace_func func, void *data)
+static size_t
+pack_backtrace(mrb_state *mrb, ptrdiff_t ciidx, struct mrb_backtrace_location *ptr)
{
- uint32_t n = 0;
+ size_t n = 0;
for (ptrdiff_t i=ciidx; i >= 0; i--) {
- struct backtrace_location loc;
+ struct mrb_backtrace_location loc;
mrb_callinfo *ci;
const mrb_code *pc;
@@ -75,59 +82,42 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, each_backtrace_func func, void *
}
loc.irep = irep;
- loc.idx = (uint32_t)(pc - loc.irep->iseq);
+ loc.idx = (uint32_t)(pc - irep->iseq);
break;
}
}
- if (func) func(mrb, &loc, data);
+ copy_backtrace(mrb, &loc, ptr, n);
n++;
}
return n;
}
-static void
-pack_backtrace_i(mrb_state *mrb,
- const struct backtrace_location *loc,
- void *data)
-{
- struct backtrace_location **pptr = (struct backtrace_location**)data;
- struct backtrace_location *ptr = *pptr;
-
- *ptr = *loc;
- *pptr = ptr+1;
-}
-
-static struct RObject*
+static struct RBasic*
packed_backtrace(mrb_state *mrb)
{
- struct RData *backtrace;
+ struct RBacktrace *backtrace;
ptrdiff_t ciidx = mrb->c->ci - mrb->c->cibase;
if (ciidx >= mrb->c->ciend - mrb->c->cibase)
ciidx = mrb->c->ciend - mrb->c->cibase; /* ciidx is broken... */
- /* count the number of backtraces */
- int len = each_backtrace(mrb, ciidx, NULL, NULL);
- backtrace = mrb_data_object_alloc(mrb, NULL, NULL, &bt_type);
- if (len > 0) {
- void *ptr = mrb_malloc(mrb, len * sizeof(struct backtrace_location));
- backtrace->data = ptr;
- backtrace->flags = len;
- each_backtrace(mrb, ciidx, pack_backtrace_i, &ptr);
- }
- else {
- backtrace->data = NULL;
- backtrace->flags = 0;
- }
- return (struct RObject*)backtrace;
+ ptrdiff_t len = ciidx + 1;
+
+ backtrace = MRB_OBJ_ALLOC(mrb, MRB_TT_BACKTRACE, NULL);
+
+ void *ptr = mrb_malloc(mrb, len * sizeof(struct mrb_backtrace_location));
+ backtrace->locations = (struct mrb_backtrace_location*)ptr;
+ backtrace->len = pack_backtrace(mrb, ciidx, backtrace->locations);
+
+ return (struct RBasic*)backtrace;
}
static void
-store_backtrace(mrb_state *mrb, mrb_value exc, struct RObject *backtrace)
+store_backtrace(mrb_state *mrb, mrb_value exc, struct RBasic *backtrace)
{
struct RException *e = mrb_exc_ptr(exc);
e->backtrace = backtrace;
- mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)backtrace);
+ mrb_field_write_barrier(mrb, (struct RBasic*)e, backtrace);
}
void
@@ -138,48 +128,52 @@ mrb_keep_backtrace(mrb_state *mrb, mrb_value exc)
if (mrb->c->ci == NULL) return;
if (mrb_exc_ptr(exc)->backtrace) return;
ai = mrb_gc_arena_save(mrb);
- struct RObject *backtrace = packed_backtrace(mrb);
+ struct RBasic *backtrace = packed_backtrace(mrb);
store_backtrace(mrb, exc, backtrace);
mrb_gc_arena_restore(mrb, ai);
}
-static struct RObject*
-mrb_unpack_backtrace(mrb_state *mrb, struct RObject *backtrace)
+static mrb_value
+decode_location(mrb_state *mrb, const struct mrb_backtrace_location *entry)
{
- const struct backtrace_location *bt;
- mrb_int n, i;
- int ai;
+ mrb_value btline;
+ int32_t lineno;
+ const char *filename;
+ if (!entry->irep || !mrb_debug_get_position(mrb, entry->irep, entry->idx, &lineno, &filename)) {
+ btline = mrb_str_new_lit(mrb, "(unknown):0");
+ }
+ else if (lineno != -1) {//debug info was available
+ btline = mrb_format(mrb, "%s:%d", filename, (int)lineno);
+ }
+ else { //all that was left was the stack frame
+ btline = mrb_format(mrb, "%s:0", filename);
+ }
+ if (entry->method_id != 0) {
+ mrb_str_cat_lit(mrb, btline, ":in ");
+ mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id));
+ }
+ return btline;
+}
+
+static struct RBasic*
+mrb_unpack_backtrace(mrb_state *mrb, struct RBasic *backtrace)
+{
if (backtrace == NULL) {
- empty_backtrace:
- return mrb_obj_ptr(mrb_ary_new_capa(mrb, 0));
+ return mrb_basic_ptr(mrb_ary_new_capa(mrb, 0));
}
if (backtrace->tt == MRB_TT_ARRAY) return backtrace;
- bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, mrb_obj_value(backtrace), &bt_type);
- if (bt == NULL) goto empty_backtrace;
- n = (mrb_int)backtrace->flags;
- if (n == 0) goto empty_backtrace;
- backtrace = mrb_obj_ptr(mrb_ary_new_capa(mrb, n));
- ai = mrb_gc_arena_save(mrb);
- for (i = 0; i < n; i++) {
- const struct backtrace_location *entry = &bt[i];
- mrb_value btline;
- int32_t lineno;
- const char *filename;
- if (!mrb_debug_get_position(mrb, entry->irep, entry->idx, &lineno, &filename)) {
- btline = mrb_str_new_lit(mrb, "(unknown):0");
- }
- else if (lineno != -1) {//debug info was available
- btline = mrb_format(mrb, "%s:%d", filename, (int)lineno);
- }
- else { //all that was left was the stack frame
- btline = mrb_format(mrb, "%s:0", filename);
- }
- if (entry->method_id != 0) {
- mrb_str_cat_lit(mrb, btline, ":in ");
- mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id));
- }
+ mrb_assert(backtrace->tt == MRB_TT_BACKTRACE);
+
+ struct RBacktrace *bt = (struct RBacktrace*)backtrace;
+ mrb_int n = bt ? (mrb_int)bt->len : 0;
+ const struct mrb_backtrace_location *loc = bt->locations;
+
+ backtrace = mrb_basic_ptr(mrb_ary_new_capa(mrb, n));
+ int ai = mrb_gc_arena_save(mrb);
+ for (mrb_int i = 0; i < n; i++) {
+ mrb_value btline = decode_location(mrb, &loc[i]);
mrb_ary_push(mrb, mrb_obj_value(backtrace), btline);
mrb_gc_arena_restore(mrb, ai);
}
@@ -190,7 +184,7 @@ mrb_unpack_backtrace(mrb_state *mrb, struct RObject *backtrace)
mrb_value
mrb_exc_backtrace(mrb_state *mrb, mrb_value exc)
{
- struct RObject *backtrace = mrb_exc_ptr(exc)->backtrace;
+ struct RBasic *backtrace = mrb_exc_ptr(exc)->backtrace;
if (backtrace == NULL) {
return mrb_nil_value();
}
@@ -212,25 +206,40 @@ mrb_get_backtrace(mrb_state *mrb)
#ifndef MRB_NO_STDIO
static void
-print_backtrace(mrb_state *mrb, struct RObject *exc, struct RArray *backtrace)
+print_backtrace(mrb_state *mrb, struct RObject *exc, struct RBasic *ptr)
{
- mrb_int i;
- mrb_int n = (backtrace ? ARY_LEN(backtrace) : 0);
- mrb_value *loc, mesg;
+ struct RArray *ary = NULL;
+ struct RBacktrace *bt = NULL;
+ mrb_int n = 0;
+
+ if (ptr) {
+ if (ptr->tt == MRB_TT_ARRAY) {
+ ary = (struct RArray*)ptr;
+ n = ARY_LEN(ary);
+ }
+ else {
+ bt = (struct RBacktrace*)ptr;
+ n = (mrb_int)bt->len;
+ }
+ }
if (n != 0) {
- if (n > 1) {
- fputs("trace (most recent call last):\n", stderr);
- }
- for (i=n-1,loc=&ARY_PTR(backtrace)[i]; i>0; i--,loc--) {
- if (mrb_string_p(*loc)) {
+ mrb_value btline;
+
+ fputs("trace (most recent call last):\n", stderr);
+ for (mrb_int i=n-1; i>0; i--) {
+ if (ary) btline = ARY_PTR(ary)[i];
+ else btline = decode_location(mrb, &bt->locations[i]);
+ if (mrb_string_p(btline)) {
fprintf(stderr, "\t[%d] ", (int)i);
- fwrite(RSTRING_PTR(*loc), (int)RSTRING_LEN(*loc), 1, stderr);
+ fwrite(RSTRING_PTR(btline), (int)RSTRING_LEN(btline), 1, stderr);
fputc('\n', stderr);
}
}
- if (mrb_string_p(*loc)) {
- fwrite(RSTRING_PTR(*loc), (int)RSTRING_LEN(*loc), 1, stderr);
+ if (ary) btline = ARY_PTR(ary)[0];
+ else btline = decode_location(mrb, &bt->locations[0]);
+ if (mrb_string_p(btline)) {
+ fwrite(RSTRING_PTR(btline), (int)RSTRING_LEN(btline), 1, stderr);
fputs(": ", stderr);
}
}
@@ -243,7 +252,7 @@ print_backtrace(mrb_state *mrb, struct RObject *exc, struct RArray *backtrace)
fwrite(nomem, sizeof(nomem)-1, 1, stderr);
}
else {
- mesg = mrb_exc_inspect(mrb, mrb_obj_value(exc));
+ mrb_value mesg = mrb_exc_inspect(mrb, mrb_obj_value(exc));
fwrite(RSTRING_PTR(mesg), RSTRING_LEN(mesg), 1, stderr);
fputc('\n', stderr);
}
@@ -261,9 +270,8 @@ mrb_print_backtrace(mrb_state *mrb)
return;
}
- struct RObject *backtrace = ((struct RException*)mrb->exc)->backtrace;
- if (backtrace && backtrace->tt != MRB_TT_ARRAY) backtrace = mrb_unpack_backtrace(mrb, backtrace);
- print_backtrace(mrb, mrb->exc, (struct RArray*)backtrace);
+ struct RBasic *backtrace = ((struct RException*)mrb->exc)->backtrace;
+ print_backtrace(mrb, mrb->exc, backtrace);
}
#else
MRB_API void
diff --git a/mruby/src/class.c b/mruby/src/class.c
index 8f33cd73..ab39a6fc 100644
--- a/mruby/src/class.c
+++ b/mruby/src/class.c
@@ -1949,10 +1949,10 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
else if (ttype == 0) {
ttype = MRB_TT_OBJECT;
}
+ if (MRB_UNDEF_ALLOCATOR_P(c)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "allocator undefined for %v", cv);
+ }
if (ttype <= MRB_TT_CPTR) {
- if (ttype == MRB_TT_UNDEF) {
- mrb_raisef(mrb, E_TYPE_ERROR, "allocator undefined for %v", cv);
- }
mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %v", cv);
}
o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
@@ -2207,6 +2207,7 @@ mrb_class_new(mrb_state *mrb, struct RClass *super)
c = boot_defclass(mrb, super);
if (super) {
MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super));
+ c->flags |= super->flags & MRB_FL_UNDEF_ALLOCATE;
}
make_metaclass(mrb, c);
diff --git a/mruby/src/error.c b/mruby/src/error.c
index c9172528..63c104c7 100644
--- a/mruby/src/error.c
+++ b/mruby/src/error.c
@@ -24,7 +24,7 @@ mrb_exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg)
if (!mrb_string_p(mesg)) {
mesg = mrb_obj_as_string(mrb, mesg);
}
- exc->mesg = mrb_obj_ptr(mesg);
+ exc->mesg = mrb_basic_ptr(mesg);
mrb_field_write_barrier_value(mrb, (struct RBasic*)exc, mesg);
}
@@ -160,7 +160,7 @@ set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace)
p++;
}
}
- mrb_exc_ptr(exc)->backtrace = mrb_obj_ptr(backtrace);
+ mrb_exc_ptr(exc)->backtrace = mrb_basic_ptr(backtrace);
mrb_field_write_barrier_value(mrb, mrb_basic_ptr(exc), backtrace);
}
diff --git a/mruby/src/fmt_fp.c b/mruby/src/fmt_fp.c
index 3eed1177..ae802075 100644
--- a/mruby/src/fmt_fp.c
+++ b/mruby/src/fmt_fp.c
@@ -319,7 +319,7 @@ mrb_format_float(mrb_float f, char *buf, size_t buf_size, char fmt, int prec, ch
}
if (*rs == '0') {
// We need to insert a 1
- if (rs[1] == '.' && fmt != 'f') {
+ if (fmt != 'f' && rs[1] == '.') {
// We're going to round 9.99 to 10.00
// Move the decimal point
rs[0] = '.';
diff --git a/mruby/src/gc.c b/mruby/src/gc.c
index 9eb84311..c5d58cb3 100644
--- a/mruby/src/gc.c
+++ b/mruby/src/gc.c
@@ -107,9 +107,11 @@
*/
+typedef struct RVALUE RVALUE;
+
struct free_obj {
MRB_OBJECT_HEADER;
- struct RBasic *next;
+ RVALUE *next;
};
struct RVALUE_initializer {
@@ -117,7 +119,7 @@ struct RVALUE_initializer {
char padding[sizeof(void*) * 4 - sizeof(uint32_t)];
};
-typedef struct {
+struct RVALUE {
union {
struct RVALUE_initializer init; /* must be first member to ensure initialization */
struct free_obj free;
@@ -136,7 +138,7 @@ typedef struct {
struct RException exc;
struct RBreak brk;
} as;
-} RVALUE;
+};
#ifdef GC_DEBUG
#define DEBUG(x) (x)
@@ -149,12 +151,11 @@ typedef struct {
#endif
typedef struct mrb_heap_page {
- struct RBasic *freelist;
+ RVALUE *freelist;
struct mrb_heap_page *next;
struct mrb_heap_page *free_next;
mrb_bool old:1;
- /* Flexible array members are not C++ compatible */
- /* void* objects[]; */
+ RVALUE objects[MRB_HEAP_PAGE_SIZE];
} mrb_heap_page;
#define GC_STEP_SIZE 1024
@@ -181,12 +182,6 @@ mrb_static_assert(MRB_GC_RED <= GC_COLOR_MASK);
#define other_white_part(s) ((s)->current_white_part ^ GC_WHITES)
#define is_dead(s, o) (((o)->color & other_white_part(s) & GC_WHITES) || (o)->tt == MRB_TT_FREE)
-/* We have removed `objects[]` from `mrb_heap_page` since it was not C++
- * compatible. Using array index to get pointer after structure instead. */
-
-/* #define objects(p) ((RVALUE*)p->objects) */
-#define objects(p) ((RVALUE*)&p[1])
-
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb);
MRB_API void*
@@ -279,7 +274,7 @@ heap_p(mrb_gc *gc, struct RBasic *object)
while (page) {
RVALUE *p;
- p = objects(page);
+ p = page->objects;
if (&p[0].as.basic <= object && object <= &p[MRB_HEAP_PAGE_SIZE - 1].as.basic) {
return TRUE;
}
@@ -299,14 +294,14 @@ mrb_object_dead_p(mrb_state *mrb, struct RBasic *object)
static void
add_heap(mrb_state *mrb, mrb_gc *gc)
{
- mrb_heap_page *page = (mrb_heap_page*)mrb_calloc(mrb, 1, sizeof(mrb_heap_page) + MRB_HEAP_PAGE_SIZE * sizeof(RVALUE));
+ mrb_heap_page *page = (mrb_heap_page*)mrb_calloc(mrb, 1, sizeof(mrb_heap_page));
RVALUE *p, *e;
- struct RBasic *prev = NULL;
+ RVALUE *prev = NULL;
- for (p = objects(page), e=p+MRB_HEAP_PAGE_SIZE; pobjects, e=p+MRB_HEAP_PAGE_SIZE; pas.free.tt = MRB_TT_FREE;
p->as.free.next = prev;
- prev = &p->as.basic;
+ prev = p;
}
page->freelist = prev;
@@ -345,7 +340,7 @@ mrb_gc_init(mrb_state *mrb, mrb_gc *gc)
#endif
}
-static void obj_free(mrb_state *mrb, struct RBasic *obj, int end);
+static void obj_free(mrb_state *mrb, struct RBasic *obj, mrb_bool end);
static void
free_heap(mrb_state *mrb, mrb_gc *gc)
@@ -357,7 +352,7 @@ free_heap(mrb_state *mrb, mrb_gc *gc)
while (page) {
tmp = page;
page = page->next;
- for (p = objects(tmp), e=p+MRB_HEAP_PAGE_SIZE; pobjects, e=p+MRB_HEAP_PAGE_SIZE; pas.free.tt != MRB_TT_FREE)
obj_free(mrb, &p->as.basic, TRUE);
}
@@ -476,7 +471,6 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls)
}
tt = MRB_INSTANCE_TT(cls);
if (tt != MRB_TT_FALSE &&
- tt != MRB_TT_UNDEF &&
ttype != MRB_TT_SCLASS &&
ttype != MRB_TT_ICLASS &&
ttype != MRB_TT_ENV &&
@@ -499,19 +493,19 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls)
add_heap(mrb, gc);
}
- struct RBasic *p = gc->free_heaps->freelist;
- gc->free_heaps->freelist = ((struct free_obj*)p)->next;
+ RVALUE *p = gc->free_heaps->freelist;
+ gc->free_heaps->freelist = p->as.free.next;
if (gc->free_heaps->freelist == NULL) {
gc->free_heaps = gc->free_heaps->free_next;
}
gc->live++;
- gc_protect(mrb, gc, p);
- *(RVALUE*)p = RVALUE_zero;
- p->tt = ttype;
- p->c = cls;
- paint_partial_white(gc, p);
- return p;
+ gc_protect(mrb, gc, &p->as.basic);
+ *p = RVALUE_zero;
+ p->as.basic.tt = ttype;
+ p->as.basic.c = cls;
+ paint_partial_white(gc, &p->as.basic);
+ return &p->as.basic;
}
static inline void
@@ -705,7 +699,7 @@ mrb_gc_mark(mrb_state *mrb, struct RBasic *obj)
}
static void
-obj_free(mrb_state *mrb, struct RBasic *obj, int end)
+obj_free(mrb_state *mrb, struct RBasic *obj, mrb_bool end)
{
DEBUG(fprintf(stderr, "obj_free(%p,tt=%d)\n",obj,obj->tt));
switch (obj->tt) {
@@ -824,6 +818,17 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
break;
#endif
+ case MRB_TT_BACKTRACE:
+ {
+ struct RBacktrace *bt = (struct RBacktrace*)obj;
+ for (size_t i = 0; i < bt->len; i++) {
+ const mrb_irep *irep = bt->locations[i].irep;
+ if (irep == NULL) continue;
+ mrb_irep_decref(mrb, (mrb_irep*)irep);
+ }
+ mrb_free(mrb, bt->locations);
+ }
+
default:
break;
}
@@ -970,6 +975,10 @@ gc_gray_counts(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
}
break;
+ case MRB_TT_BACKTRACE:
+ children += ((struct RBacktrace*)obj)->len;
+ break;
+
default:
break;
}
@@ -1065,7 +1074,7 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
size_t tried_sweep = 0;
while (page && (tried_sweep < limit)) {
- RVALUE *p = objects(page);
+ RVALUE *p = page->objects;
RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
size_t freed = 0;
mrb_bool dead_slot = TRUE;
@@ -1081,7 +1090,7 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
obj_free(mrb, &p->as.basic, FALSE);
if (p->as.basic.tt == MRB_TT_FREE) {
p->as.free.next = page->freelist;
- page->freelist = (struct RBasic*)p;
+ page->freelist = p;
freed++;
}
else {
@@ -1525,7 +1534,7 @@ gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback,
while (page != NULL) {
RVALUE *p;
- p = objects(page);
+ p = page->objects;
for (int i=0; i < MRB_HEAP_PAGE_SIZE; i++) {
if ((*callback)(mrb, &p[i].as.basic, data) == MRB_EACH_OBJ_BREAK)
return;
diff --git a/mruby/src/numeric.c b/mruby/src/numeric.c
index 5b098c8b..41951e6b 100644
--- a/mruby/src/numeric.c
+++ b/mruby/src/numeric.c
@@ -744,18 +744,14 @@ flo_lshift(mrb_state *mrb, mrb_value x)
/* 15.2.9.3.13 */
/*
+ * Document-method: Float#to_f
+ *
* call-seq:
* flt.to_f -> self
*
* As flt
is already a float, returns +self+.
*/
-static mrb_value
-flo_to_f(mrb_state *mrb, mrb_value num)
-{
- return num;
-}
-
/* 15.2.9.3.11 */
/*
* call-seq:
@@ -1105,19 +1101,17 @@ flo_abs(mrb_state *mrb, mrb_value num)
/* 15.2.9.3.24 */
/*
+ * Document-method: Integer#to_i
+ * Document-method: Integer#to_int
+ *
* call-seq:
* int.to_i -> integer
+ * int.to_int -> integer
*
* As int is already an Integer
, all these
* methods simply return the receiver.
*/
-static mrb_value
-int_to_i(mrb_state *mrb, mrb_value num)
-{
- return num;
-}
-
mrb_value
mrb_int_mul(mrb_state *mrb, mrb_value x, mrb_value y)
{
@@ -1976,7 +1970,6 @@ MRB_API mrb_value
mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
{
char buf[MRB_INT_BIT+1];
- mrb_int val = mrb_integer(x);
if (base < 2 || 36 < base) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base);
@@ -1986,6 +1979,7 @@ mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
return mrb_bint_to_s(mrb, x, base);
}
#endif
+ mrb_int val = mrb_integer(x);
const char *p = mrb_int_to_cstr(buf, sizeof(buf), val, base);
mrb_assert(p != NULL);
mrb_value str = mrb_str_new_cstr(mrb, p);
@@ -2031,6 +2025,9 @@ cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
if (mrb_bigint_p(v1)) {
return mrb_bint_cmp(mrb, v1, v2);
}
+ if (mrb_bigint_p(v2)) {
+ return mrb_bint_cmp(mrb, mrb_bint_new_int(mrb, mrb_integer(v1)), v2);
+ }
#endif
#ifdef MRB_NO_FLOAT
@@ -2227,7 +2224,8 @@ mrb_init_numeric(mrb_state *mrb)
/* Integer Class */
mrb->integer_class = integer = mrb_define_class_id(mrb, MRB_SYM(Integer), numeric); /* 15.2.8 */
- MRB_SET_INSTANCE_TT(integer, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(integer, MRB_TT_INTEGER);
+ MRB_UNDEF_ALLOCATOR(integer);
mrb_undef_class_method_id(mrb, integer, MRB_SYM(new));
mrb_define_method_id(mrb, integer, MRB_OPSYM(pow), int_pow, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, integer, MRB_OPSYM(cmp), num_cmp, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
@@ -2236,8 +2234,8 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method_id(mrb, integer, MRB_OPSYM(gt), num_gt, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, integer, MRB_OPSYM(ge), num_ge, MRB_ARGS_REQ(1));
- mrb_define_method_id(mrb, integer, MRB_SYM(to_i), int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
- mrb_define_method_id(mrb, integer, MRB_SYM(to_int), int_to_i, MRB_ARGS_NONE());
+ mrb_define_method_id(mrb, integer, MRB_SYM(to_i), mrb_obj_itself, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
+ mrb_define_method_id(mrb, integer, MRB_SYM(to_int), mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method_id(mrb, integer, MRB_OPSYM(add), int_add, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
mrb_define_method_id(mrb, integer, MRB_OPSYM(sub), int_sub, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
@@ -2272,7 +2270,8 @@ mrb_init_numeric(mrb_state *mrb)
#ifndef MRB_NO_FLOAT
/* Float Class */
mrb->float_class = fl = mrb_define_class_id(mrb, MRB_SYM(Float), numeric); /* 15.2.9 */
- MRB_SET_INSTANCE_TT(fl, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(fl, MRB_TT_FLOAT);
+ MRB_UNDEF_ALLOCATOR(fl);
mrb_undef_class_method(mrb, fl, "new");
mrb_define_method_id(mrb, fl, MRB_OPSYM(pow), flo_pow, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, fl, MRB_OPSYM(div), flo_div, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */
@@ -2299,7 +2298,7 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method_id(mrb, fl, MRB_SYM(floor), flo_floor, MRB_ARGS_OPT(1)); /* 15.2.9.3.10 */
mrb_define_method_id(mrb, fl, MRB_SYM_Q(infinite),flo_infinite_p, MRB_ARGS_NONE()); /* 15.2.9.3.11 */
mrb_define_method_id(mrb, fl, MRB_SYM(round), flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */
- mrb_define_method_id(mrb, fl, MRB_SYM(to_f), flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */
+ mrb_define_method_id(mrb, fl, MRB_SYM(to_f), mrb_obj_itself, MRB_ARGS_NONE()); /* 15.2.9.3.13 */
mrb_define_method_id(mrb, fl, MRB_SYM(to_i), flo_to_i, MRB_ARGS_NONE()); /* 15.2.9.3.14 */
mrb_define_method_id(mrb, fl, MRB_SYM(truncate), flo_truncate, MRB_ARGS_OPT(1)); /* 15.2.9.3.15 */
mrb_define_method_id(mrb, fl, MRB_SYM(divmod), flo_divmod, MRB_ARGS_REQ(1));
diff --git a/mruby/src/object.c b/mruby/src/object.c
index f8e9c0b7..8fbcc0f5 100644
--- a/mruby/src/object.c
+++ b/mruby/src/object.c
@@ -649,3 +649,9 @@ mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
if (mrb_class(mrb, obj1) != mrb_class(mrb, obj2)) return FALSE;
return mrb_test(mrb_funcall_argv(mrb, obj1, MRB_SYM_Q(eql), 1, &obj2));
}
+
+MRB_API mrb_value
+mrb_obj_itself(mrb_state *mrb, mrb_value self)
+{
+ return self;
+}
diff --git a/mruby/src/proc.c b/mruby/src/proc.c
index 978813f7..6aca2b84 100644
--- a/mruby/src/proc.c
+++ b/mruby/src/proc.c
@@ -490,9 +490,8 @@ mrb_init_proc(mrb_state *mrb)
mrb_method_t m;
struct RClass *pc = mrb->proc_class = mrb_define_class_id(mrb, MRB_SYM(Proc), mrb->object_class); /* 15.2.17 */
- MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);
-
- MRB_SET_INSTANCE_TT(pc, MRB_TT_UNDEF);
+ MRB_SET_INSTANCE_TT(pc, MRB_TT_PROC);
+ MRB_UNDEF_ALLOCATOR(pc);
mrb_define_class_method_id(mrb, pc, MRB_SYM(new), mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
mrb_define_method_id(mrb, pc, MRB_SYM(initialize_copy), mrb_proc_init_copy, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, pc, MRB_SYM(arity), proc_arity, MRB_ARGS_NONE()); /* 15.2.17.4.2 */
diff --git a/mruby/src/state.c b/mruby/src/state.c
index 3f48756e..35ea71e2 100644
--- a/mruby/src/state.c
+++ b/mruby/src/state.c
@@ -58,18 +58,6 @@ mrb_open_core(mrb_allocf f, void *ud)
return mrb;
}
-void*
-mrb_default_allocf(mrb_state *mrb, void *p, size_t size, void *ud)
-{
- if (size == 0) {
- free(p);
- return NULL;
- }
- else {
- return realloc(p, size);
- }
-}
-
MRB_API mrb_state*
mrb_open(void)
{
@@ -173,6 +161,9 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
}
mrb_free(mrb, (void*)irep->lv);
mrb_debug_info_free(mrb, irep->debug_info);
+#ifdef MRB_DEBUG
+ memset(irep, -1, sizeof(*irep));
+#endif
mrb_free(mrb, irep);
}
diff --git a/mruby/src/string.c b/mruby/src/string.c
index b7e3a650..780ab4e5 100644
--- a/mruby/src/string.c
+++ b/mruby/src/string.c
@@ -263,7 +263,138 @@ mrb_gc_free_str(mrb_state *mrb, struct RString *str)
mrb_free(mrb, str->as.heap.ptr);
}
+#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
+ defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
+ defined(__mc68020__)
+# define ALIGNED_WORD_ACCESS 0
+#else
+# define ALIGNED_WORD_ACCESS 1
+#endif
+
#ifdef MRB_UTF8_STRING
+
+#define NOASCII(c) ((c) & 0x80)
+
+#ifdef SIMPLE_SEARCH_NONASCII
+/* the naive implementation. define SIMPLE_SEARCH_NONASCII, */
+/* if you need it for any constraint (e.g. code size). */
+static const char*
+search_nonascii(const char* p, const char *e)
+{
+ for (; p < e; ++p) {
+ if (NOASCII(*p)) return p;
+ }
+ return e;
+}
+
+#elif defined(__SSE2__)
+# include
+
+static inline const char *
+search_nonascii(const char *p, const char *e)
+{
+ if (sizeof(__m128i) < (size_t)(e - p)) {
+ if (!_mm_movemask_epi8(_mm_loadu_si128((__m128i const*)p))) {
+ const intptr_t lowbits = sizeof(__m128i) - 1;
+ const __m128i *s, *t;
+ s = (const __m128i*)(~lowbits & ((intptr_t)p + lowbits));
+ t = (const __m128i*)(~lowbits & (intptr_t)e);
+ for (; s < t; ++s) {
+ if (_mm_movemask_epi8(_mm_load_si128(s))) break;
+ }
+ p = (const char *)s;
+ }
+ }
+ switch (e - p) {
+ default:
+ case 15: if (NOASCII(*p)) return p; ++p;
+ case 14: if (NOASCII(*p)) return p; ++p;
+ case 13: if (NOASCII(*p)) return p; ++p;
+ case 12: if (NOASCII(*p)) return p; ++p;
+ case 11: if (NOASCII(*p)) return p; ++p;
+ case 10: if (NOASCII(*p)) return p; ++p;
+ case 9: if (NOASCII(*p)) return p; ++p;
+ case 8: if (NOASCII(*p)) return p; ++p;
+ case 7: if (NOASCII(*p)) return p; ++p;
+ case 6: if (NOASCII(*p)) return p; ++p;
+ case 5: if (NOASCII(*p)) return p; ++p;
+ case 4: if (NOASCII(*p)) return p; ++p;
+ case 3: if (NOASCII(*p)) return p; ++p;
+ case 2: if (NOASCII(*p)) return p; ++p;
+ case 1: if (NOASCII(*p)) return p; ++p;
+ if (NOASCII(*p)) return p;
+ }
+ return e;
+}
+
+#else
+
+#ifdef MRB_64BIT
+# define NONASCII_MASK 0x8080808080808080ULL
+#else /* MRB_32BIT */
+# define NONASCII_MASK 0x80808080UL
+#endif
+
+static const char*
+search_nonascii(const char *p, const char *e)
+{
+ if (e - p >= sizeof(void*)) {
+#if ALIGNED_WORD_ACCESS
+ if ((uintptr_t)p % sizeof(void*)) {
+ int l = sizeof(void*) - (uintptr_t)p % sizeof(void*);
+ p += l;
+ switch (l) {
+#ifdef MRB_64BIT
+ case 7: if (p[-7]&0x80) return p-7;
+ case 6: if (p[-6]&0x80) return p-6;
+ case 5: if (p[-5]&0x80) return p-5;
+ case 4: if (p[-4]&0x80) return p-4;
+#endif
+ case 3: if (p[-3]&0x80) return p-3;
+ case 2: if (p[-2]&0x80) return p-2;
+ case 1: if (p[-1]&0x80) return p-1;
+ case 0: break;
+ }
+ }
+#endif
+
+ const uintptr_t *s = (uintptr_t*)p;
+ const uintptr_t *t = (uintptr_t*)(e - (sizeof(void*)-1));
+
+ for (;s < t; s++) {
+ if (*s & NONASCII_MASK) {
+ p = (const char*)s;
+ if (NOASCII(p[0])) return p+0;
+ if (NOASCII(p[1])) return p+1;
+ if (NOASCII(p[2])) return p+2;
+ if (NOASCII(p[3])) return p+3;
+#ifdef MRB_64BIT
+ if (NOASCII(p[4])) return p+4;
+ if (NOASCII(p[5])) return p+5;
+ if (NOASCII(p[6])) return p+6;
+ if (NOASCII(p[7])) return p+7;
+#endif
+ }
+ }
+ }
+ switch (e - p) {
+ default:
+#ifdef MRB_64BIT
+ case 7: if (e[-7]&0x80) return e-7;
+ case 6: if (e[-6]&0x80) return e-6;
+ case 5: if (e[-5]&0x80) return e-5;
+ case 4: if (e[-4]&0x80) return e-4;
+#endif
+ case 3: if (e[-3]&0x80) return e-3;
+ case 2: if (e[-2]&0x80) return e-2;
+ case 1: if (e[-1]&0x80) return e-1;
+ }
+ return e;
+}
+
+#endif /* SIMPLE_SEARCH_NONASCII */
+
#define utf8_islead(c) ((unsigned char)((c)&0xc0) != 0x80)
extern const char mrb_utf8len_table[];
@@ -278,7 +409,7 @@ mrb_utf8len(const char* p, const char* e)
mrb_int len = mrb_utf8len_table[(unsigned char)p[0] >> 3];
if (len > e - p) return 1;
switch (len) {
- case 1:
+ case 0:
return 1;
case 4:
if (utf8_islead(p[3])) return 1;
@@ -309,12 +440,12 @@ utf8_strlen(mrb_value str)
struct RString *s = mrb_str_ptr(str);
mrb_int byte_len = RSTR_LEN(s);
- if (RSTR_ASCII_P(s)) {
+ if (RSTR_SINGLE_BYTE_P(s)) {
return byte_len;
}
else {
mrb_int utf8_len = mrb_utf8_strlen(RSTR_PTR(s), byte_len);
- if (byte_len == utf8_len) RSTR_SET_ASCII_FLAG(s);
+ if (byte_len == utf8_len) RSTR_SET_SINGLE_BYTE_FLAG(s);
return utf8_len;
}
}
@@ -325,33 +456,62 @@ utf8_strlen(mrb_value str)
static mrb_int
chars2bytes(mrb_value s, mrb_int off, mrb_int idx)
{
- if (RSTR_ASCII_P(mrb_str_ptr(s))) {
+ if (RSTR_SINGLE_BYTE_P(mrb_str_ptr(s))) {
return idx;
}
- else {
- mrb_int i, b, n;
- const char *p = RSTRING_PTR(s) + off;
- const char *e = RSTRING_END(s);
- for (b=i=0; p= slen) {
- const char *pivot;
-
- if (memcmp(p, s, slen) == 0) {
- return off;
- }
-
- pivot = p + qstable[(unsigned char)p[slen - 1]];
- if (pivot >= pend || pivot < p /* overflowed */) { return -1; }
-
- do {
- p += mrb_utf8len(p, pend);
- off++;
- } while (p < pivot);
- }
-
- return -1;
-}
-
static mrb_int
str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
{
- const char *p = RSTRING_PTR(str);
- const char *pend = p + RSTRING_LEN(str);
- const char *s = RSTRING_PTR(sub);
- const mrb_int slen = RSTRING_LEN(sub);
- mrb_int off = pos;
+ const char *ptr = RSTRING_PTR(sub);
+ mrb_int len = RSTRING_LEN(sub);
- for (; pos > 0; pos --) {
- if (pend - p < 1) { return -1; }
- p += mrb_utf8len(p, pend);
+ if (pos > 0) {
+ pos = chars2bytes(str, 0, pos);
}
- if (slen < 1) { return off; }
+ pos = mrb_str_index(mrb, str, ptr, len, pos);
- return str_index_str_by_char_search(mrb, p, pend, s, slen, off);
+ if (pos > 0) {
+ pos = bytes2chars(str, pos);
+ }
+ return pos;
}
-#define BYTES_ALIGN_CHECK(pos) if (pos < 0) return mrb_nil_value();
#else
#define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
-#define chars2bytes(p, off, ci) (ci)
-#define bytes2chars(p, end, bi) (bi)
+#define chars2bytes(s, off, ci) (ci)
+#define bytes2chars(s, bi) (bi)
#define char_adjust(beg, end, ptr) (ptr)
#define char_backtrack(ptr, end) ((end) - 1)
-#define BYTES_ALIGN_CHECK(pos)
-#define str_index_str_by_char(mrb, str, sub, pos) str_index_str(mrb, str, sub, pos)
-#endif
-
-#ifndef MRB_QS_SHORT_STRING_LENGTH
-#define MRB_QS_SHORT_STRING_LENGTH 2048
+#define str_index_str_by_char(mrb, str, sub, pos) str_index_str((mrb), (str), (sub), (pos))
#endif
+/* memsearch_swar (SWAR stands for SIMD within a register) */
+/* See https://en.wikipedia.org/wiki/SWAR */
+/* The function is taken from http://0x80.pl/articles/simd-strfind.html */
+/* The original source code is under 2-clause BSD license; see LEGAL file. */
+/* The modifications:
+ * port from C++ to C
+ * returns mrb_int
+ * remove alignment issue
+ * support bigendian CPU
+ * fixed potential buffer overflow
+*/
static inline mrb_int
-mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
+memsearch_swar(const char *xs, mrb_int m, const char *ys, mrb_int n)
{
- if (n + m < MRB_QS_SHORT_STRING_LENGTH) {
- const unsigned char *y = ys;
- const unsigned char *ye = ys+n-m+1;
+#ifdef MRB_64BIT
+#define bitint uint64_t
+#define MASK1 0x0101010101010101ull
+#define MASK2 0x7f7f7f7f7f7f7f7full
+#define MASK3 0x8080808080808080ull
+#else
+#define bitint uint32_t
+#define MASK1 0x01010101ul
+#define MASK2 0x7f7f7f7ful
+#define MASK3 0x80808080ul
+#endif
+#if defined(MRB_ENDIAN_BIG)
+#ifdef MRB_64BIT
+#define MASK4 0x8000000000000000ull
+#else
+#define MASK4 0x80000000ul
+#endif
+#else
+#define MASK4 0x80
+#endif
+
+ const bitint first = MASK1 * (uint8_t)xs[0];
+ const bitint last = MASK1 * (uint8_t)xs[m-1];
+
+ const char *s0 = ys;
+ const char *s1 = ys+m-1;
+
+ const mrb_int lim = n - m - (mrb_int)sizeof(bitint);
+ mrb_int i;
+
+ for (i=0; i < lim; i+=sizeof(bitint)) {
+ bitint t0, t1;
- for (;;) {
- y = (const unsigned char*)memchr(y, xs[0], (size_t)(ye-y));
- if (y == NULL) return -1;
- if (memcmp(xs, y, m) == 0) {
- return (mrb_int)(y - ys);
+ memcpy(&t0, s0+i, sizeof(bitint));
+ memcpy(&t1, s1+i, sizeof(bitint));
+
+ const bitint eq = (t0 ^ first) | (t1 ^ last);
+ bitint zeros = ((~eq & MASK2) + MASK1) & (~eq & MASK3);
+
+
+ for (size_t j = 0; zeros; j++) {
+ if (zeros & MASK4) {
+ const mrb_int idx = i + j;
+ const char* p = s0 + idx + 1;
+ if (memcmp(p, xs + 1, m - 2) == 0) {
+ return idx;
+ }
}
- y++;
+
+#if defined(MRB_ENDIAN_BIG)
+ zeros <<= 8;
+#else
+ zeros >>= 8;
+#endif
}
- return -1;
}
- else {
- const unsigned char *x = xs, *xe = xs + m;
- const unsigned char *y = ys;
- ptrdiff_t qstable[256];
-
- /* Preprocessing */
- for (int i = 0; i < 256; i++)
- qstable[i] = m + 1;
- for (; x < xe; x++)
- qstable[*x] = xe - x;
- /* Searching */
- for (; y + m <= ys + n; y += *(qstable + y[m])) {
- if (*xs == *y && memcmp(xs, y, m) == 0)
- return (mrb_int)(y - ys);
+
+ if (i+m < n) {
+ const char *p = s0;
+ const char *e = ys + n;
+ for (;p n) return -1;
else if (m == n) {
- return memcmp(x0, y0, m) == 0 ? 0 : -1;
+ return memcmp(x, y, m) == 0 ? 0 : -1;
}
else if (m < 1) {
return 0;
}
else if (m == 1) {
- const unsigned char *ys = (const unsigned char*)memchr(y, *x, n);
+ const char *p = (const char*)memchr(y, *x, n);
- if (ys)
- return (mrb_int)(ys - y);
- else
- return -1;
+ if (p) return (mrb_int)(p - y);
+ return -1;
}
- return mrb_memsearch_qs((const unsigned char*)x0, m, (const unsigned char*)y0, n);
+ return memsearch_swar(x, m, y, n);
}
static void
@@ -551,21 +711,16 @@ mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
s->as.heap.ptr += (mrb_ssize)beg;
s->as.heap.len = (mrb_ssize)len;
}
- RSTR_COPY_ASCII_FLAG(s, orig);
+ RSTR_COPY_SINGLE_BYTE_FLAG(s, orig);
return mrb_obj_value(s);
}
-static void
-str_range_to_bytes(mrb_value str, mrb_int *pos, mrb_int *len)
-{
- *pos = chars2bytes(str, 0, *pos);
- *len = chars2bytes(str, *pos, *len);
-}
#ifdef MRB_UTF8_STRING
static inline mrb_value
str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
- str_range_to_bytes(str, &beg, &len);
+ beg = chars2bytes(str, 0, beg);
+ len = chars2bytes(str, beg, len);
return mrb_str_byte_subseq(mrb, str, beg, len);
}
#else
@@ -639,7 +794,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
mrb_check_frozen(mrb, s1);
if (s1 == s2) return mrb_obj_value(s1);
- RSTR_COPY_ASCII_FLAG(s1, s2);
+ RSTR_COPY_SINGLE_BYTE_FLAG(s1, s2);
if (RSTR_SHARED_P(s1)) {
str_decref(mrb, s1->as.heap.aux.shared);
}
@@ -765,7 +920,7 @@ MRB_API void
mrb_str_modify(mrb_state *mrb, struct RString *s)
{
mrb_str_modify_keep_ascii(mrb, s);
- RSTR_UNSET_ASCII_FLAG(s);
+ RSTR_UNSET_SINGLE_BYTE_FLAG(s);
}
MRB_API mrb_value
@@ -903,7 +1058,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self)
memcpy(p + n, p, len-n);
}
p[RSTR_LEN(str2)] = '\0';
- RSTR_COPY_ASCII_FLAG(str2, mrb_str_ptr(self));
+ RSTR_COPY_SINGLE_BYTE_FLAG(str2, mrb_str_ptr(self));
return mrb_obj_value(str2);
}
@@ -1213,7 +1368,7 @@ str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect)
char buf[4]; /* `\x??` or UTF-8 character */
mrb_value result = mrb_str_new_lit(mrb, "\"");
#ifdef MRB_UTF8_STRING
- uint32_t ascii_flag = MRB_STR_ASCII;
+ uint32_t sb_flag = MRB_STR_SINGLE_BYTE;
#endif
p = RSTRING_PTR(str); pend = RSTRING_END(str);
@@ -1225,7 +1380,7 @@ str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect)
if (clen > 1) {
mrb_str_cat(mrb, result, p, clen);
p += clen-1;
- ascii_flag = 0;
+ sb_flag = 0;
continue;
}
}
@@ -1267,11 +1422,11 @@ str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect)
mrb_str_cat_lit(mrb, result, "\"");
#ifdef MRB_UTF8_STRING
if (inspect) {
- mrb_str_ptr(str)->flags |= ascii_flag;
- mrb_str_ptr(result)->flags |= ascii_flag;
+ mrb_str_ptr(str)->flags |= sb_flag;
+ mrb_str_ptr(result)->flags |= sb_flag;
}
else {
- RSTR_SET_ASCII_FLAG(mrb_str_ptr(result));
+ RSTR_SET_SINGLE_BYTE_FLAG(mrb_str_ptr(result));
}
#endif
@@ -1297,7 +1452,8 @@ mrb_str_aset(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen, mrb_
if (beg < 0 || beg > charlen) { str_out_of_index(mrb, indx); }
/* fall through */
case STR_CHAR_RANGE_CORRECTED:
- str_range_to_bytes(str, &beg, &len);
+ beg = chars2bytes(str, 0, beg);
+ len = chars2bytes(str, beg, len);
/* fall through */
case STR_BYTE_RANGE_CORRECTED:
if (mrb_int_add_overflow(beg, len, &len)) {
@@ -1791,7 +1947,7 @@ mrb_str_byteindex_m(mrb_state *mrb, mrb_value str)
static mrb_value
mrb_str_index_m(mrb_state *mrb, mrb_value str)
{
- if (RSTR_ASCII_P(mrb_str_ptr(str))) {
+ if (RSTR_SINGLE_BYTE_P(mrb_str_ptr(str))) {
return mrb_str_byteindex_m(mrb, str);
}
@@ -2062,7 +2218,7 @@ mrb_str_byterindex_m(mrb_state *mrb, mrb_value str)
static mrb_value
mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
{
- if (RSTR_ASCII_P(mrb_str_ptr(str))) {
+ if (RSTR_SINGLE_BYTE_P(mrb_str_ptr(str))) {
return mrb_str_byterindex_m(mrb, str);
}
@@ -2070,8 +2226,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
mrb_int pos;
if (mrb_get_args(mrb, "S|i", &sub, &pos) == 1) {
- pos = RSTRING_CHAR_LEN(str);
- pos = chars2bytes(str, 0, pos);
+ pos = RSTRING_LEN(str);
}
else if (pos >= 0) {
pos = chars2bytes(str, 0, pos);
@@ -2087,8 +2242,8 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
}
pos = str_rindex(mrb, str, sub, pos);
if (pos >= 0) {
- pos = bytes2chars(RSTRING_PTR(str), RSTRING_LEN(str), pos);
- BYTES_ALIGN_CHECK(pos);
+ pos = bytes2chars(str, pos);
+ if (pos < 0) return mrb_nil_value();
return mrb_int_value(mrb, pos);
}
return mrb_nil_value();
diff --git a/mruby/src/symbol.c b/mruby/src/symbol.c
index 3f0ddb53..021b8000 100644
--- a/mruby/src/symbol.c
+++ b/mruby/src/symbol.c
@@ -441,6 +441,8 @@ sym_name(mrb_state *mrb, mrb_value vsym)
/* 15.2.11.3.4 */
/*
+ * Document-method: Symbol#to_sym
+ *
* call-seq:
* sym.to_sym -> sym
* sym.intern -> sym
@@ -450,12 +452,6 @@ sym_name(mrb_state *mrb, mrb_value vsym)
* in this case.
*/
-static mrb_value
-sym_to_sym(mrb_state *mrb, mrb_value sym)
-{
- return sym;
-}
-
/* 15.2.11.3.5(x) */
/*
* call-seq:
@@ -696,7 +692,7 @@ mrb_init_symbol(mrb_state *mrb)
mrb_define_method_id(mrb, sym, MRB_SYM(to_s), sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */
mrb_define_method_id(mrb, sym, MRB_SYM(name), sym_name, MRB_ARGS_NONE());
- mrb_define_method_id(mrb, sym, MRB_SYM(to_sym), sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */
+ mrb_define_method_id(mrb, sym, MRB_SYM(to_sym), mrb_obj_itself, MRB_ARGS_NONE()); /* 15.2.11.3.4 */
mrb_define_method_id(mrb, sym, MRB_SYM(inspect), sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */
mrb_define_method_id(mrb, sym, MRB_OPSYM(cmp), sym_cmp, MRB_ARGS_REQ(1));
}
diff --git a/mruby/src/vm.c b/mruby/src/vm.c
index 35e1650f..fc9a2b39 100644
--- a/mruby/src/vm.c
+++ b/mruby/src/vm.c
@@ -1121,9 +1121,8 @@ break_new(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci, mrb_value
#define MRB_CATCH_FILTER_ALL (MRB_CATCH_FILTER_RESCUE | MRB_CATCH_FILTER_ENSURE)
static const struct mrb_irep_catch_handler *
-catch_handler_find(mrb_state *mrb, mrb_callinfo *ci, const mrb_code *pc, uint32_t filter)
+catch_handler_find(const mrb_irep *irep, const mrb_code *pc, uint32_t filter)
{
- const mrb_irep *irep;
ptrdiff_t xpc;
size_t cnt;
const struct mrb_irep_catch_handler *e;
@@ -1131,9 +1130,7 @@ catch_handler_find(mrb_state *mrb, mrb_callinfo *ci, const mrb_code *pc, uint32_
/* The comparison operators use `>` and `<=` because pc already points to the next instruction */
#define catch_cover_p(pc, beg, end) ((pc) > (ptrdiff_t)(beg) && (pc) <= (ptrdiff_t)(end))
- if (ci->proc == NULL || MRB_PROC_CFUNC_P(ci->proc)) return NULL;
- irep = ci->proc->body.irep;
- if (irep == NULL || irep->clen < 1) return NULL;
+ mrb_assert(irep && irep->clen > 0);
xpc = pc - irep->iseq;
/* If it retry at the top level, pc will be 0, so check with -1 as the start position */
mrb_assert(catch_cover_p(xpc, -1, irep->ilen));
@@ -1142,7 +1139,7 @@ catch_handler_find(mrb_state *mrb, mrb_callinfo *ci, const mrb_code *pc, uint32_
/* Currently uses a simple linear search to avoid processing complexity. */
cnt = irep->clen;
e = mrb_irep_catch_handler_table(irep) + cnt - 1;
- for (; cnt > 0; cnt --, e --) {
+ for (; cnt > 0; cnt--, e--) {
if (((UINT32_C(1) << e->type) & filter) &&
catch_cover_p(xpc, mrb_irep_catch_handler_unpack(e->begin), mrb_irep_catch_handler_unpack(e->end))) {
return e;
@@ -1231,8 +1228,8 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci
#define UNWIND_ENSURE(mrb, ci, pc, tag, return_ci, val) \
do { \
- ch = catch_handler_find(mrb, ci, pc, MRB_CATCH_FILTER_ENSURE); \
- if (ch) { \
+ if ((proc = (ci)->proc) && !MRB_PROC_CFUNC_P(proc) && (irep = proc->body.irep) && irep->clen > 0 && \
+ (ch = catch_handler_find(irep, pc, MRB_CATCH_FILTER_ENSURE))) { \
THROW_TAGGED_BREAK(mrb, tag, return_ci, val); \
} \
} while (0)
@@ -1692,8 +1689,8 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
mrb_assert(a >= 0 && a < irep->ilen);
}
CHECKPOINT_MAIN(RBREAK_TAG_JUMP) {
- ch = catch_handler_find(mrb, mrb->c->ci, pc, MRB_CATCH_FILTER_ENSURE);
- if (ch) {
+ if (irep->clen > 0 &&
+ (ch = catch_handler_find(irep, pc, MRB_CATCH_FILTER_ENSURE))) {
/* avoiding a jump from a catch handler into the same handler */
if (a < mrb_irep_catch_handler_unpack(ch->begin) || a >= mrb_irep_catch_handler_unpack(ch->end)) {
THROW_TAGGED_BREAK(mrb, RBREAK_TAG_JUMP, mrb->c->ci, mrb_fixnum_value(a));
@@ -1747,14 +1744,67 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
}
CASE(OP_RAISEIF, B) {
- mrb_value exc = regs[a];
- if (mrb_break_p(exc)) {
+ mrb_value exc;
+ exc = regs[a];
+ if (mrb_nil_p(exc)) {
+ mrb->exc = NULL;
+ }
+ else if (mrb_break_p(exc)) {
+ struct RBreak *brk;
mrb->exc = mrb_obj_ptr(exc);
- goto L_BREAK;
+ L_BREAK:
+ brk = (struct RBreak*)mrb->exc;
+ switch (mrb_break_tag_get(brk)) {
+#define DISPATCH_CHECKPOINTS(n, i) case n: goto CHECKPOINT_LABEL_MAKE(n);
+ RBREAK_TAG_FOREACH(DISPATCH_CHECKPOINTS)
+#undef DISPATCH_CHECKPOINTS
+ default:
+ mrb_assert(!"wrong break tag");
+ }
}
- mrb_exc_set(mrb, exc);
- if (mrb->exc) {
- goto L_RAISE;
+ else {
+ mrb_callinfo *ci;
+ mrb_exc_set(mrb, exc);
+ L_RAISE:
+ ci = mrb->c->ci;
+ while (!(proc = ci->proc) || MRB_PROC_CFUNC_P(ci->proc) || !(irep = proc->body.irep) || irep->clen < 1 ||
+ (ch = catch_handler_find(irep, ci->pc, MRB_CATCH_FILTER_ALL)) == NULL) {
+ if (ci != mrb->c->cibase) {
+ ci = cipop(mrb);
+ if (ci[1].cci == CINFO_SKIP) {
+ mrb_assert(prev_jmp != NULL);
+ mrb->jmp = prev_jmp;
+ MRB_THROW(prev_jmp);
+ }
+ }
+ else if (mrb->c == mrb->root_c) {
+ mrb->c->ci->stack = mrb->c->stbase;
+ goto L_STOP;
+ }
+ else {
+ struct mrb_context *c = mrb->c;
+
+ c->status = MRB_FIBER_TERMINATED;
+ mrb->c = c->prev;
+ if (!mrb->c) mrb->c = mrb->root_c;
+ else c->prev = NULL;
+ if (!c->vmexec) goto L_RAISE;
+ mrb->jmp = prev_jmp;
+ if (!prev_jmp) return mrb_obj_value(mrb->exc);
+ MRB_THROW(prev_jmp);
+ }
+ }
+
+ if (FALSE) {
+ L_CATCH_TAGGED_BREAK: /* from THROW_TAGGED_BREAK() or UNWIND_ENSURE() */
+ ci = mrb->c->ci;
+ }
+ proc = ci->proc;
+ irep = proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ stack_extend(mrb, irep->nregs);
+ pc = irep->iseq + mrb_irep_catch_handler_unpack(ch->target);
}
NEXT;
}
@@ -1827,57 +1877,62 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
}
ci->cci = CINFO_NONE;
- if (MRB_METHOD_CFUNC_P(m)) {
- if (MRB_METHOD_PROC_P(m)) {
- struct RProc *p = MRB_METHOD_PROC(m);
- CI_PROC_SET(ci, p);
- recv = p->body.func(mrb, recv);
+ if (MRB_METHOD_PROC_P(m)) {
+ const struct RProc *p = MRB_METHOD_PROC(m);
+ /* handle alias */
+ if (MRB_PROC_ALIAS_P(p)) {
+ ci->mid = p->body.mid;
+ p = p->upper;
+ }
+ CI_PROC_SET(ci, p);
+ if (!MRB_PROC_CFUNC_P(p)) {
+ /* setup environment for calling method */
+ proc = p;
+ irep = proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ stack_extend(mrb, (irep->nregs < 4) ? 4 : irep->nregs);
+ pc = irep->iseq;
+ JUMP;
}
else {
- if (MRB_METHOD_NOARG_P(m) && (ci->n > 0 || ci->nk > 0)) {
+ if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
check_method_noarg(mrb, ci);
}
- recv = MRB_METHOD_FUNC(m)(mrb, recv);
- }
- mrb_assert(mrb->c->ci > mrb->c->cibase);
- mrb_gc_arena_shrink(mrb, ai);
- if (mrb->exc) goto L_RAISE;
- ci = mrb->c->ci;
- if (!ci->u.target_class) { /* return from context modifying method (resume/yield) */
- if (ci->cci == CINFO_RESUMED) {
- mrb->jmp = prev_jmp;
- return recv;
- }
- else {
- mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc));
- proc = ci[-1].proc;
- irep = proc->body.irep;
- pool = irep->pool;
- syms = irep->syms;
- }
+ recv = MRB_PROC_CFUNC(p)(mrb, recv);
}
- ci->stack[0] = recv;
- /* pop stackpos */
- ci = cipop(mrb);
- pc = ci->pc;
}
else {
- /* setup environment for calling method */
- proc = MRB_METHOD_PROC(m);
- /* handle alias */
- if (MRB_PROC_ALIAS_P(proc)) {
- ci->mid = proc->body.mid;
- proc = proc->upper;
+ if (MRB_METHOD_NOARG_P(m) && (ci->n > 0 || ci->nk > 0)) {
+ check_method_noarg(mrb, ci);
}
- CI_PROC_SET(ci, proc);
- irep = proc->body.irep;
- pool = irep->pool;
- syms = irep->syms;
- stack_extend(mrb, (irep->nregs < 4) ? 4 : irep->nregs);
- pc = irep->iseq;
+ recv = MRB_METHOD_FUNC(m)(mrb, recv);
}
+
+ /* cfunc epilogue */
+ mrb_gc_arena_shrink(mrb, ai);
+ if (mrb->exc) goto L_RAISE;
+ ci = mrb->c->ci;
+ if (!ci->u.target_class) { /* return from context modifying method (resume/yield) */
+ if (ci->cci == CINFO_RESUMED) {
+ mrb->jmp = prev_jmp;
+ return recv;
+ }
+ else {
+ mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc));
+ proc = ci[-1].proc;
+ irep = proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ }
+ }
+ mrb_assert(ci > mrb->c->cibase);
+ ci->stack[0] = recv;
+ /* pop stackpos */
+ ci = cipop(mrb);
+ pc = ci->pc;
+ JUMP;
}
- JUMP;
CASE(OP_CALL, Z) {
mrb_callinfo *ci = mrb->c->ci;
@@ -1914,7 +1969,6 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
if (!irep) {
mrb->c->ci->stack[0] = mrb_nil_value();
a = 0;
- c = OP_R_NORMAL;
goto L_OP_RETURN_BODY;
}
mrb_int nargs = ci_bidx(ci)+1;
@@ -2209,200 +2263,144 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
}
CASE(OP_BREAK, B) {
- c = OP_R_BREAK;
- goto L_RETURN;
+ if (mrb->exc) {
+ goto L_RAISE;
+ }
+
+ if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN;
+ if (MRB_PROC_ORPHAN_P(proc) || !MRB_PROC_ENV_P(proc) || !MRB_ENV_ONSTACK_P(MRB_PROC_ENV(proc))) {
+ L_BREAK_ERROR:
+ RAISE_LIT(mrb, E_LOCALJUMP_ERROR, "break from proc-closure");
+ }
+ else {
+ struct REnv *e = MRB_PROC_ENV(proc);
+
+ if (e->cxt != mrb->c) {
+ goto L_BREAK_ERROR;
+ }
+ }
+ mrb_callinfo *ci = mrb->c->ci;
+ proc = proc->upper;
+ while (mrb->c->cibase < ci && ci[-1].proc != proc) {
+ ci--;
+ }
+ if (ci == mrb->c->cibase) {
+ goto L_BREAK_ERROR;
+ }
+ c = a; // release the "a" variable, which can handle 32-bit values
+ a = ci - mrb->c->cibase;
+ goto L_UNWINDING;
}
CASE(OP_RETURN_BLK, B) {
- c = OP_R_RETURN;
- goto L_RETURN;
+ if (mrb->exc) {
+ goto L_RAISE;
+ }
+
+ mrb_callinfo *ci = mrb->c->ci;
+
+ if (!MRB_PROC_ENV_P(proc) || MRB_PROC_STRICT_P(proc)) {
+ goto NORMAL_RETURN;
+ }
+
+ const struct RProc *dst;
+ mrb_callinfo *cibase;
+ cibase = mrb->c->cibase;
+ dst = top_proc(mrb, proc);
+
+ if (MRB_PROC_ENV_P(dst)) {
+ struct REnv *e = MRB_PROC_ENV(dst);
+
+ if (!MRB_ENV_ONSTACK_P(e) || (e->cxt && e->cxt != mrb->c)) {
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
+ goto L_RAISE;
+ }
+ }
+ /* check jump destination */
+ while (cibase <= ci && ci->proc != dst) {
+ ci--;
+ }
+ if (ci <= cibase) { /* no jump destination */
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
+ goto L_RAISE;
+ }
+ c = a; // release the "a" variable, which can handle 32-bit values
+ a = ci - mrb->c->cibase;
+ goto L_UNWINDING;
}
- CASE(OP_RETURN, B)
- c = OP_R_NORMAL;
- L_RETURN:
- {
+ CASE(OP_RETURN, B) {
mrb_callinfo *ci;
ci = mrb->c->ci;
if (mrb->exc) {
- L_RAISE:
- ci = mrb->c->ci;
- while ((ch = catch_handler_find(mrb, ci, ci->pc, MRB_CATCH_FILTER_ALL)) == NULL) {
- if (ci != mrb->c->cibase) {
- ci = cipop(mrb);
- if (ci[1].cci == CINFO_SKIP) {
- mrb_assert(prev_jmp != NULL);
- mrb->jmp = prev_jmp;
- MRB_THROW(prev_jmp);
- }
- }
- else if (mrb->c == mrb->root_c) {
- mrb->c->ci->stack = mrb->c->stbase;
- goto L_STOP;
- }
- else {
- struct mrb_context *c = mrb->c;
-
- c->status = MRB_FIBER_TERMINATED;
- mrb->c = c->prev;
- if (!mrb->c) mrb->c = mrb->root_c;
- else c->prev = NULL;
- if (!c->vmexec) goto L_RAISE;
- mrb->jmp = prev_jmp;
- if (!prev_jmp) return mrb_obj_value(mrb->exc);
- MRB_THROW(prev_jmp);
- }
- }
-
- if (FALSE) {
- L_CATCH_TAGGED_BREAK: /* from THROW_TAGGED_BREAK() or UNWIND_ENSURE() */
- ci = mrb->c->ci;
- }
- proc = ci->proc;
- irep = proc->body.irep;
- pool = irep->pool;
- syms = irep->syms;
- stack_extend(mrb, irep->nregs);
- pc = irep->iseq + mrb_irep_catch_handler_unpack(ch->target);
+ goto L_RAISE;
}
else {
mrb_int acc;
mrb_value v;
+ NORMAL_RETURN:
ci = mrb->c->ci;
- v = regs[a];
- mrb_gc_protect(mrb, v);
- switch (c) {
- case OP_R_RETURN:
- /* Fall through to OP_R_NORMAL otherwise */
- if (ci->cci == CINFO_NONE && MRB_PROC_ENV_P(proc) && !MRB_PROC_STRICT_P(proc)) {
- const struct RProc *dst;
- mrb_callinfo *cibase;
- cibase = mrb->c->cibase;
- dst = top_proc(mrb, proc);
-
- if (MRB_PROC_ENV_P(dst)) {
- struct REnv *e = MRB_PROC_ENV(dst);
-
- if (!MRB_ENV_ONSTACK_P(e) || (e->cxt && e->cxt != mrb->c)) {
- localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
- goto L_RAISE;
- }
- }
- /* check jump destination */
- while (cibase <= ci && ci->proc != dst) {
- if (ci->cci > CINFO_NONE) { /* jump cross C boundary */
- localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
- goto L_RAISE;
- }
- ci--;
- }
- if (ci <= cibase) { /* no jump destination */
- localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
- goto L_RAISE;
- }
- break;
- }
- /* fallthrough */
- case OP_R_NORMAL:
- NORMAL_RETURN:
- if (ci == mrb->c->cibase) {
- struct mrb_context *c;
- c = mrb->c;
-
- if (!c->prev) {
- if (c != mrb->root_c) {
- /* fiber termination should transfer to root */
- c->prev = mrb->root_c;
- }
- else { /* toplevel return */
- regs[irep->nlocals] = v;
- goto CHECKPOINT_LABEL_MAKE(RBREAK_TAG_STOP);
- }
- }
- else if (!c->vmexec && c->prev->ci == c->prev->cibase) {
- RAISE_LIT(mrb, E_FIBER_ERROR, "double resume");
- }
- }
- break;
- case OP_R_BREAK:
- if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN;
- if (MRB_PROC_ORPHAN_P(proc) || !MRB_PROC_ENV_P(proc) || !MRB_ENV_ONSTACK_P(MRB_PROC_ENV(proc))) {
- L_BREAK_ERROR:
- RAISE_LIT(mrb, E_LOCALJUMP_ERROR, "break from proc-closure");
- }
- else {
- struct REnv *e = MRB_PROC_ENV(proc);
-
- if (e->cxt != mrb->c) {
- goto L_BREAK_ERROR;
- }
- }
- proc = proc->upper;
- while (mrb->c->cibase < ci && ci[-1].proc != proc) {
- ci--;
- }
- if (ci == mrb->c->cibase) {
- goto L_BREAK_ERROR;
- }
- if (FALSE) {
- struct RBreak *brk;
- L_BREAK:
- brk = (struct RBreak*)mrb->exc;
- ci = &mrb->c->cibase[brk->ci_break_index];
- proc = ci->proc;
- v = mrb_break_value_get(brk);
- pc = ci->pc;
+ if (ci == mrb->c->cibase) {
+ struct mrb_context *c;
+ c = mrb->c;
- switch (mrb_break_tag_get(brk)) {
-#define DISPATCH_CHECKPOINTS(n, i) case n: goto CHECKPOINT_LABEL_MAKE(n);
- RBREAK_TAG_FOREACH(DISPATCH_CHECKPOINTS)
-#undef DISPATCH_CHECKPOINTS
- default:
- mrb_assert(!"wrong break tag");
- }
+ if (c->prev && !c->vmexec && c->prev->ci == c->prev->cibase) {
+ RAISE_LIT(mrb, E_FIBER_ERROR, "double resume");
}
- break;
- default:
- /* cannot happen */
- break;
}
- for (;;) {
- CHECKPOINT_RESTORE(RBREAK_TAG_BREAK) {
+ v = regs[a];
+ mrb_gc_protect(mrb, v);
+ CHECKPOINT_RESTORE(RBREAK_TAG_BREAK) {
+ if (TRUE) {
struct RBreak *brk = (struct RBreak*)mrb->exc;
ci = &mrb->c->cibase[brk->ci_break_index];
v = mrb_break_value_get(brk);
- mrb_gc_protect(mrb, v);
}
- CHECKPOINT_MAIN(RBREAK_TAG_BREAK) {
- UNWIND_ENSURE(mrb, mrb->c->ci, mrb->c->ci->pc, RBREAK_TAG_BREAK, ci, v);
+ else {
+ L_UNWINDING: // for a check on the role of `a` and `c`, see `goto L_UNWINDING`
+ ci = mrb->c->cibase + a;
+ v = regs[c];
}
- CHECKPOINT_END(RBREAK_TAG_BREAK);
+ mrb_gc_protect(mrb, v);
+ }
+ CHECKPOINT_MAIN(RBREAK_TAG_BREAK) {
+ for (;;) {
+ UNWIND_ENSURE(mrb, mrb->c->ci, mrb->c->ci->pc, RBREAK_TAG_BREAK, ci, v);
- if (mrb->c->ci == ci) {
- break;
- }
- cipop(mrb);
- if (mrb->c->ci[1].cci != CINFO_NONE) {
- mrb_assert(prev_jmp != NULL);
- mrb->exc = (struct RObject*)break_new(mrb, RBREAK_TAG_BREAK, ci, v);
- mrb_gc_arena_restore(mrb, ai);
- mrb->c->vmexec = FALSE;
- mrb->jmp = prev_jmp;
- MRB_THROW(prev_jmp);
+ if (mrb->c->ci == ci) {
+ break;
+ }
+ cipop(mrb);
+ if (mrb->c->ci[1].cci != CINFO_NONE) {
+ mrb_assert(prev_jmp != NULL);
+ mrb->exc = (struct RObject*)break_new(mrb, RBREAK_TAG_BREAK, ci, v);
+ mrb_gc_arena_restore(mrb, ai);
+ mrb->c->vmexec = FALSE;
+ mrb->jmp = prev_jmp;
+ MRB_THROW(prev_jmp);
+ }
}
}
+ CHECKPOINT_END(RBREAK_TAG_BREAK);
mrb->exc = NULL; /* clear break object */
if (ci == mrb->c->cibase) {
struct mrb_context *c = mrb->c;
- /* automatic yield at the end */
+ if (c == mrb->root_c) {
+ /* toplevel return */
+ regs[irep->nlocals] = v;
+ goto L_STOP;
+ }
+
+ /* fiber termination should automatic yield or transfer to root */
c->status = MRB_FIBER_TERMINATED;
- mrb->c = c->prev;
- mrb->c->status = MRB_FIBER_RUNNING;
+ mrb->c = c->prev ? c->prev : mrb->root_c;
c->prev = NULL;
- if (c->vmexec) {
+ mrb->c->status = MRB_FIBER_RUNNING;
+ if (c->vmexec ||
+ (mrb->c == mrb->root_c && mrb->c->ci == mrb->c->cibase) /* case using Fiber#transfer in mrb_fiber_resume() */) {
mrb_gc_arena_restore(mrb, ai);
c->vmexec = FALSE;
mrb->jmp = prev_jmp;