Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for FFI while leaving legacy implementations intact #11483

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
394321f
branch to support FFI
JasonLunn Oct 31, 2022
11fcd23
restore protobuf.rb
JasonLunn Oct 31, 2022
09a7114
native implementation
JasonLunn Oct 31, 2022
1e50c8b
restore protobuf.rb
JasonLunn Oct 31, 2022
6cc806c
Refactor `protobuf.rb` to separate native and ffi implementations.
JasonLunn Oct 31, 2022
dfc7dbb
Fix spelling `Unsupport` -> `Unsupported`
JasonLunn Jan 6, 2023
fb395f8
Fix exception raising by properly instantiating the exception.
JasonLunn Jan 6, 2023
d9767ca
Add check on `PROTOCOL_BUFFERS_RUBY_IMPLEMENTATION` environment varia…
JasonLunn Jan 6, 2023
3792576
Add FFI implementation
JasonLunn Jan 6, 2023
589629d
Add ffi flags
mkruskal-google Jan 10, 2023
2ec3aa3
Refactor convert.c to separate CRuby-specific glue that has dependenc…
JasonLunn Jan 11, 2023
a5ff141
Fix copy/paste casting bug.
JasonLunn Jan 11, 2023
cec7850
Refactor message.c to separate CRuby-specific glue that has dependenc…
JasonLunn Jan 11, 2023
4734f34
Have shared_convert methods invoke shared_message methods directly.
JasonLunn Jan 11, 2023
55cd7fe
branch to support FFI
JasonLunn Oct 31, 2022
2f3838b
restore protobuf.rb
JasonLunn Oct 31, 2022
c8656c4
native implementation
JasonLunn Oct 31, 2022
1c19455
restore protobuf.rb
JasonLunn Oct 31, 2022
f461e72
Refactor `protobuf.rb` to separate native and ffi implementations.
JasonLunn Oct 31, 2022
1b1e64e
Fix spelling `Unsupport` -> `Unsupported`
JasonLunn Jan 6, 2023
4cbcd56
Fix exception raising by properly instantiating the exception.
JasonLunn Jan 6, 2023
5d71437
Stop ignoring shared source files; ignore FFI Compiler output directo…
JasonLunn Jul 6, 2023
b402119
Update function names and arguments.
JasonLunn Jul 6, 2023
f7083f1
Remove references to `PROTOCOL_BUFFERS_RUBY_IMPLEMENTATION`.
JasonLunn Jul 6, 2023
039af51
Relocate shared files.
JasonLunn Jul 6, 2023
8607cda
Temporarily update visibility, pending update to upb repo.
JasonLunn Jul 6, 2023
1a716c0
Create glue.
JasonLunn Jul 6, 2023
e7240f8
Fix unit tests.
JasonLunn Jul 7, 2023
8f95755
Rebase
JasonLunn Oct 31, 2022
1dff209
restore protobuf.rb
JasonLunn Oct 31, 2022
f4c08b2
Rebase
JasonLunn Oct 31, 2022
e32280e
restore protobuf.rb
JasonLunn Oct 31, 2022
536f9b3
Rebase
JasonLunn Oct 31, 2022
c665a79
Fix spelling `Unsupport` -> `Unsupported`
JasonLunn Jan 6, 2023
78a2928
Fix exception raising by properly instantiating the exception.
JasonLunn Jan 6, 2023
a7aa7aa
Rebase
JasonLunn Jan 6, 2023
bcc6f6c
Rebase
JasonLunn Jan 11, 2023
8336d0a
Refactor message.c to separate CRuby-specific glue that has dependenc…
JasonLunn Jan 11, 2023
88f1506
Have shared_convert methods invoke shared_message methods directly.
JasonLunn Jan 11, 2023
3089818
Fix merge damage
JasonLunn Jul 7, 2023
95c4535
Call `upb_Arena_Malloc()` directly.
JasonLunn Jul 7, 2023
0286c71
Address PR feedback.
JasonLunn Jul 7, 2023
2fd1eac
Cleanup debug print.
JasonLunn Jul 7, 2023
3d1d1fe
Revert changes to ruby-upb.h.
JasonLunn Jul 10, 2023
0d575d5
Merge remote-tracking branch 'upstream/main' into simultaneous_ffi
JasonLunn Jul 10, 2023
8920f9d
Update to the new Ruby-native ObjectCache.
JasonLunn Jul 10, 2023
72d6ee8
Allow fallback to native CRuby implementation when FFI doesn't load.
JasonLunn Jul 10, 2023
a3eb317
Introduce a new test that the expected implementation is used.
JasonLunn Jul 12, 2023
bc87afb
Merge remote-tracking branch 'upstream/main' into simultaneous_ffi
JasonLunn Jul 12, 2023
ca80881
Merge branch 'main' into simultaneous_ffi
JasonLunn Jul 13, 2023
2c8d0ef
Use the FFI-fix branch of rules_ruby.
JasonLunn Jul 14, 2023
2a1cf7c
Use backwards compatible range syntax.
JasonLunn Jul 14, 2023
e28e256
Move most calls to `attach_function` out of `ffi.rb`.
JasonLunn Jul 15, 2023
55f2884
Breakout conformance tests by platform and whether FFI is enabled.
JasonLunn Jul 15, 2023
03a32da
Merge remote-tracking branch 'upstream/main' into simultaneous_ffi
JasonLunn Jul 15, 2023
472b653
Remove workaround for access to UPI API functions.
JasonLunn Jul 16, 2023
af40b04
Default JRuby to autodetecting FFI but make CRuby request it explicitly.
JasonLunn Jul 17, 2023
839a3d7
Make all interpreters opt-in for FFI.
JasonLunn Jul 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Rebase
  • Loading branch information
JasonLunn committed Jul 7, 2023
commit bcc6f6c2645ff0300aa97db09940dab179a40ff9
62 changes: 62 additions & 0 deletions ruby/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ rescue LoadError
USE_FFI = false
end

USE_FFI = ENV['PROTOCOL_BUFFERS_RUBY_IMPLEMENTATION'] == 'ffi'

require "ffi-compiler/compile_task" if USE_FFI

spec = Gem::Specification.load("google-protobuf.gemspec")

well_known_protos = %w[
Expand Down Expand Up @@ -186,6 +190,61 @@ else
unless ENV['IN_DOCKER'] == 'true'
task :build => [:copy_third_party]
end
end

task :copy_shared do
FileUtils.cp(Dir.glob("ext/google/shared/*.{c,h}"), "ext/google/protobuf_c")
end

if USE_FFI
# FFI::CompilerTask's constructor walks the filesystem at initialization time
# in order to create subtasks for each source file, so the files from third_party
# must be copied into place before the task is defined.
ffi_compiler_config_block = Proc.new do |c|
c.cflags << "-std=gnu99 -O3 -DNDEBUG"
if RbConfig::CONFIG['target_os'] =~ /darwin|linux/
# c.cflags << "-fvisibility=hidden -Wall -Wsign-compare -Wno-declaration-after-statement"
c.cflags << "-Wall -Wsign-compare -Wno-declaration-after-statement"
end
if RbConfig::CONFIG['target_os'] =~ /linux/
# Instruct the linker to point memcpy calls at our __wrap_memcpy wrapper.
c.ldflags << "-Wl,-wrap,memcpy"
end
end

if File.exist? 'ext/google/protobuf_c/third_party/utf8_range'
desc "compiler tasks"
namespace "ffi-compiler" do
FFI::Compiler::CompileTask.new('ext/google/protobuf_c', &ffi_compiler_config_block)
end
else
task "ffi-compiler:default" do
Rake::Task[:copy_third_party].invoke
desc "compiler tasks"
namespace "ffi-compiler" do
FFI::Compiler::CompileTask.new('ext/google/protobuf_c', &ffi_compiler_config_block)
Rake::Task[Rake::Task[:default].prereqs.first].invoke
end
end
end
else
if RUBY_PLATFORM == "java"
task :clean => :require_mvn do
system("mvn --batch-mode clean")
end

task :compile => :require_mvn do
system("mvn --batch-mode package")
end

task :require_mvn do
raise ArgumentError, "maven needs to be installed" if `which mvn` == ''
end

else
unless ENV['IN_DOCKER'] == 'true'
task :build => [:copy_third_party, :copy_shared]
end

Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
unless RUBY_PLATFORM =~ /darwin/
Expand Down Expand Up @@ -238,6 +297,9 @@ else
task 'gem:native' => [:genproto, 'gem:windows', 'gem:java']
end
end
end

task :compile => ["ffi-compiler:default"] if USE_FFI

task :compile => ["ffi-compiler:default"] if USE_FFI

Expand Down
85 changes: 85 additions & 0 deletions ruby/ext/google/shared/shared_convert.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// 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
// OWNER 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.

// -----------------------------------------------------------------------------
// Ruby <-> upb data conversion functions. Strictly free of dependencies on
// Ruby interpreter internals.

#include "shared_convert.h"

bool shared_Msgval_IsEqual(upb_MessageValue val1, upb_MessageValue val2,
upb_CType type, upb_MessageDef* msgdef, upb_Status* status) {
switch (type) {
case kUpb_CType_Bool:
return memcmp(&val1, &val2, 1) == 0;
case kUpb_CType_Float:
case kUpb_CType_Int32:
case kUpb_CType_UInt32:
case kUpb_CType_Enum:
return memcmp(&val1, &val2, 4) == 0;
case kUpb_CType_Double:
case kUpb_CType_Int64:
case kUpb_CType_UInt64:
return memcmp(&val1, &val2, 8) == 0;
case kUpb_CType_String:
case kUpb_CType_Bytes:
return val1.str_val.size == val2.str_val.size &&
memcmp(val1.str_val.data, val2.str_val.data, val1.str_val.size) ==
0;
case kUpb_CType_Message:
return Message_Equal(val1.msg_val, val2.msg_val, msgdef);
default:
upb_Status_SetErrorMessage(status, "Internal error, unexpected type");
}
}

uint64_t shared_Msgval_GetHash(upb_MessageValue val, upb_CType type, upb_MessageDef* msgdef,
uint64_t seed, upb_Status* status) {
switch (type) {
case kUpb_CType_Bool:
return _upb_Hash(&val, 1, seed);
case kUpb_CType_Float:
case kUpb_CType_Int32:
case kUpb_CType_UInt32:
case kUpb_CType_Enum:
return _upb_Hash(&val, 4, seed);
case kUpb_CType_Double:
case kUpb_CType_Int64:
case kUpb_CType_UInt64:
return _upb_Hash(&val, 8, seed);
case kUpb_CType_String:
case kUpb_CType_Bytes:
return _upb_Hash(val.str_val.data, val.str_val.size, seed);
case kUpb_CType_Message:
return Message_Hash(val.msg_val, msgdef, seed);
default:
upb_Status_SetErrorMessage(status, "Internal error, unexpected type");
}
}
41 changes: 41 additions & 0 deletions ruby/ext/google/shared/shared_convert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// 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
// OWNER 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.

// -----------------------------------------------------------------------------
// Ruby <-> upb data conversion functions. Strictly free of dependencies on
// Ruby interpreter internals.

#include "ruby-upb.h"

bool shared_Msgval_IsEqual(upb_MessageValue val1, upb_MessageValue val2,
upb_CType type, upb_MessageDef* msgdef, upb_Status* status);

uint64_t shared_Msgval_GetHash(upb_MessageValue val, upb_CType type, upb_MessageDef* msgdef,
uint64_t seed, upb_Status* status);